Max Shlain
Max Shlain

Reputation: 117

Copy-Item copies folder inside the target when running second time

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

Upvotes: 4

Views: 2020

Answers (2)

KUTlime
KUTlime

Reputation: 8047

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

Upvotes: 0

Martin Brandl
Martin Brandl

Reputation: 58931

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.

Upvotes: 4

Related Questions