Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move files that contain a string to a subfolder with the same name as the original (PowerShell)

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?

like image 337
Joseph Greenfield Avatar asked Dec 01 '25 06:12

Joseph Greenfield


2 Answers

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.

  1. Your folders should not have any other subfolders under "sub_1, sub_2, ..., sub_n" else they will attempt to move incorrectly. This can be addressed with a little more string manipulation. In an attempt to make the code terse using -Recurse created this caveat.
like image 125
Matt Avatar answered Dec 04 '25 00:12

Matt


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"
        }
    }
}
like image 21
Nathan Rice Avatar answered Dec 03 '25 22:12

Nathan Rice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!