Search code examples
powershell

transfer the files from sub folder and sub folders recursively without specifying the folder name


I have a PowerShell script that copies the files that starts with 4 digits from source directory to destination directory. The destination directory never changes. Below is the script and it works well:

Get-ChildItem -Recurse -File -LiteralPath D:\Test | Where-Object { $_.Name -match '^\d{4}' } | Copy-Item -Destination D:\transferTo\  

Is it possible that I don't need to change the subfolder and sub sub folder every time and the PowerShell script gets the source folder in the loop so for eg. I have two screen shots below:

enter image description here

enter image description here

Test1 is a sub folder inside test folder. I manually specified the folder D:\test and then I need to again manually change the path to transfer the files from D:\Test\Test1. Can this be done recursively without manual changes. I tried doing this:

Get-ChildItem -Recurse -File -LiteralPath D:*.* | Where-Object { $_.Name -match '^\d{4}' } | Copy-Item -Destination D:\transferTo\

Putting . so that it gets all the folders, sub folders and sub sub folders, but I get an error with this:

enter image description here


Solution

  • Requirements a bit unclear.

    • Do you want to simply not re-write the source directory every time?

      Then use $pwd for -Path.
      It's the Automatic Variable with the Present Working Directory as in "the directory from where you are calling the command".

      Get-ChildItem -File -Path $pwd |
      Where-Object -Property BaseName -Match '\d{4}' |
      Copy-Item -Destination 'D:\transferTo\'

    • You want to "get all files in one directory AND all its sub-directories"?

      Then you just need to add the parameter -Recurse to Get-ChildItem.

    And, of course, you can use them together.

    A note: if you are going to use it in a script, I suggest to parameterize it:

    Script.ps1:

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)][string]$Path,
        [Parameter()][switch]$Recurse,
        [Parameter()][string]$RegexFilter = '\d{4}'
        [Parameter()][string]$Destination = 'D:\transferTo\'
    )
    
    Get-ChildItem -File -Path $Path -Recurse:$Recurse.IsPresent | 
        Where-Object -Property BaseName -Match $RegexFilter |
        Copy-Item -Destination $Destination