Search code examples
stringpowershellmovesubdirectory

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?


Solution

  • 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.