4

During repetitive logs collection on my internal system, found strange behavior of recursive Copy-Item call

Say, i have C:\Source with some files and subfolders with files. I want to copy this recursively to C:\Target. For first time all source will be copied recursively to C:\Target

The problem happens when i try to copy "C:\Source" to "C:\Target" for second time. In this case will "C:\Source" will be copied to "C:\Target\Source"

For example:

cls
if(Test-Path "C:\Target")
{
    Remove-Item "C:\Target"
}

Copy-Item "C:\Source" "C:\Target" -Force -Recurse | Out-Null
DIR "C:\Target" 
Write-Host "OK"
Write-Host " "
Write-Host " "

Copy-Item "C:\Source" "C:\Target" -Force -Recurse | Out-Null
DIR "C:\Target" 
Write-Host "Not OK"

Script output:

Directory: C:\Target


Mode                LastWriteTime     Length Name                                                          
----                -------------     ------ ----                                                          
d----         4/11/2016   3:45 PM            SampleSourceFolderLevel1                                      
-a---         4/11/2016   3:35 PM          0 SampleFileLevel0.txt                                          
OK


d----         4/11/2016   3:45 PM            SampleSourceFolderLevel1                                      
d----         4/11/2016   3:45 PM            Source                                                        
-a---         4/11/2016   3:35 PM          0 SampleFileLevel0.txt                                          
Not OK

Any idea how can i make Copy-Item to work like

ROBOCOPY $sourceLog $targetLog /E | Out-Null 

??

Thanks in advance

Script output

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
Max Shlain
  • 67
  • 1
  • 6

2 Answers2

4

Seems like you want to copy the content of c:\Source. You just need to add \*:

Copy-Item -Path "C:\Source\*" -Destination "C:\Target" -Force -Recurse | Out-Null

It works for the first run because you delete the target folder and the cmdlet now copies the folder C:\Source to C:\Target. If C:\Targetexists, the cmdlet will copy the source into the Target folder.

Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • Unfortunately, this copies only first level files items of **C:\Source**. If it has a sub-folder **C:\Source\Subfolder**, it will not be copied – Max Shlain Apr 11 '16 at 13:05
  • Thanks, @jisaak. I see that this works for second time, but still does not work fine for first :). Do you know how to overcome this without creating target folder prior to copy item? [link] (http://i.imgur.com/BXgA75j.png) – Max Shlain Apr 11 '16 at 13:16
  • The easiest solution would be to ensure the folder exists using `md 'C:\Target' -Force | out-null` – Martin Brandl Apr 11 '16 at 13:32
  • Thank you, @jisaak. That's the solution that i applied. Another option is to use robocopy. I just wanted to know if there any way to get consistent behavior from Copy-Item – Max Shlain Apr 11 '16 at 14:37
0

Copy-Item has inconsistent behaviour based on the fact if the destination exist or not.

If you want to have a consistent copy experience, use this pattern:

$copyFrom = 'C:\Foo\Bar\TargetDirectoryToCopy'
$destinationPath = 'D:\Bar\Foo\'

$newItemParams = @{
    Path        = $destinationPath
    ItemType    = 'Directory'
    Force       = $True
}

$copyParams = @{
    Path        = $copyFrom
    Destination = $destinationPath
    Recurse     = $True
    Confirm     = $false
    Force       = $True
}
New-Item @newItemParams
Copy-Item @copyParams

Result

The directory D:\Bar\Foo\ will have TargetDirectoryToCopy directory nested inside.

So if there is a file C:\Foo\Bar\TargetDirectoryToCopy\FooBar.txt, its copy will be created as D:\Bar\Foo\TargetDirectoryToCopy\FooBar.txt along with any another file in C:\Foo\Bar\TargetDirectoryToCopy

KUTlime
  • 5,889
  • 1
  • 18
  • 29