Move the files containing the string to a subfolder with the same name as the original (PowerShell)
I am using PowerShell and two days later I am struggling with this issue.
In the C: \ dir_1 directory I have many sub-folders (sub_1, sub_2, ..., sub_n). Each of them contains several text files. For each subfolder i = 1,2, ..., n, I want to move text files containing the string "My-String" to the directory C: \ dir_2 \ sub_i.
For example, if the X file in the path C: \ dir1 \ sub_5 contains the string "My-String", I want to move it to the C: \ dir_2 \ sub_5 folder. The destination folder already exists.
I tried several modifications of the following code, but it doesn't work:
Get-ChildItem "C:\dir_1" | Where-Object {$_.PSIsContainer -eq $True} | Foreach-Object {Get-ChildItem "C:\dir_1\$_" | Select-String -pattern "My-String" | group path | select name | %{Move-Item $_.name "C:\dir_2\$_"}}
So, basically, I tried to do this: ineach subfolder in dir_1, take the files containing the string and move them to a subfolder in dir_2 with the same name. I have tried several small modifications to this code, but I cannot get around my mistakes. Major error: "move-item: the given path format is not supported" ... any help?
source to share
I feel like I can do better, but this is my first approach
$dir1 = "C:\temp\data\folder1"
$dir2 = "C:\temp\data\folder2"
$results = Get-ChildItem $dir1 -recurse | Select-String -Pattern "asdf"
$results | ForEach-Object{
$parentFolder = ($_.Path -split "\\")[-2]
Move-Item -Path $_.Path -Destination ([io.path]::combine($dir2,$parentFolder))
}
Select-String
can take file paths to enter its pipeline. We pass all files under $dir1
with -recurse
to get all of its children in subfolders. $results
will contain an array of match objects. One of the properties is the path to the corresponding file.
With all of these, $results
we then go through each one and extract the parent folder from the path. Then connect this folder to the path $dir2
to move it to its destination.
There are several assumptions we make here. We could take some of them into account, if necessary. I mentioned the one I know might be the problem in the first place.
- There should be no other subfolders under "sub_1, sub_2, ..., sub_n" in your folders, otherwise they will try to navigate incorrectly. This can be solved with a little more rigorous manipulation. In an attempt to make the code concise with help
-recurse
created this caveat.
source to share
Here's one liner that does what you want too:
Get-ChildItem "C:\dir_1" | Where-Object {$_.PSIsContainer -eq $True} | ForEach-Object {$SubDirName = $_.Name;ForEach ($File in $(Get-ChildItem $_.FullName)){If ($File.Name -like "*My-String*"){Move-Item $File.FullName "C:\dir_2\$SubDirName"}}}
And if you want it to be so broken up, as Matt replied:
$ParentDir = Get-ChildItem "C:\dir_1" | Where-Object {$_.PSIsContainer -eq $True}
ForEach ($SubDir in $ParentDir){
$SubDirName = $SubDir.Name
ForEach ($File in $(Get-ChildItem $SubDir.FullName)){
If ($File.Name -like "*My-String*"){
Move-Item $File.FullName "C:\dir_2\$SubDirName"
}
}
}
source to share