How to use PowerShell copy-item and keep structure

I have a directory structure that looks like this:

C:\folderA\folderB\folderC\client1\f1\files
C:\folderA\folderB\folderC\client1\f2\files
C:\folderA\folderB\folderC\client2\f1\files
C:\folderA\folderB\folderC\client2\f2\files
C:\folderA\folderB\folderC\client3\f1\files
C:\folderA\folderB\folderC\client4\f2\files

I want to copy the content of the f1 folders in C:\tmp\ to get this

C:\tmp\client1\f1\files
C:\tmp\client2\f1\files
C:\tmp\client3\f1\files

I tried this:

Copy-Item -recur -path: "*/f1/" -destination: C:\tmp\

But it copies the contents without copying the structure correctly.


Solution 1:

In PowerShell version 3.0 and newer this is simply done this way:

Get-ChildItem -Path $sourceDir | Copy-Item -Destination $targetDir -Recurse -Container

Reference: Get-ChildItem

Solution 2:

PowerShell:

$sourceDir = 'c:\folderA\folderB\folderC\client1\f1'
$targetDir = ' c:\tmp\'

Get-ChildItem $sourceDir -filter "*" -recurse | `
    foreach{
        $targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
        New-Item -ItemType File -Path $targetFile -Force;
        Copy-Item $_.FullName -destination $targetFile
    }

Note:

  • The -filter "*" does not do anything. It is just here to illustrate if you want to copy some specific files. E.g. all *.config files.
  • Still have to call a New-Item with -Force to actually create the folder structure.

Solution 3:

I have been digging around and found a lot of solutions to this issue, all being some alteration, not just a straight copy-item command. Granted, some of these questions predate PowerShell 3.0 so the answers are not wrong, but using PowerShell 3.0 I was finally able to accomplish this using the -Container switch for Copy-Item:

Copy-Item $from $to -Recurse -Container

This was the test I ran, no errors and the destination folder represented the same folder structure:

New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt

# NOTE: with no \ at the end of the destination, the file
#       is created in the root of the destination, and
#       it does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container

# If the destination does not exist, this created the
# matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container