I'm using PowerShell and it is two days that I'm struggling on this issue.
In the directory C:\dir_1 I have many subfolders (sub_1, sub_2, ..., sub_n). Each of them contains several text files. For each subfolder i=1,2,...,n, I want to move the text files that contain the string "My-String" to the directory C:\dir_2\sub_i.
For example, if the file X in the path C:\dir1\sub_5 contains the string "My-String", I want to move it to the location C:\dir_2\sub_5. The destination folder is already existing.
I tried several modifications of the following code, but it does not 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, what I tried to do is: foreach subfolder in dir_1, take the files that contain the string and move them to the subfolder in dir_2 with the same name. I tried several small modifications of that code, but I cannot get around my mistakes. The main error is "move-item: The given path format is not supported"... any help?
I feel like I could 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 for its pipeline input. We feed it all the files that are under $dir1 using -recurse to get all of its children in sub folders. $results would contain an array of match objects. One of the properties is the path of the matched file.
With all of those $results we then go though each and extract the parent folder from the path. Then combine that folder with the path $dir2 in order to move it to it destination.
There are several assumptions that we are taking here. Some we could account for if need be. I will mention the one I know could be an issue first.
-Recurse created this caveat. Here is a 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'd like to see it broken out like Matt's answer:
$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"
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With