replace robocopy options with copy-item

Brass Contributor

Hello,

 

I want to get rid of robocopy in some old scripts and use powershell copy-item instead.

 

Here is a typical line :

.\robocopy.exe "\\$sourceserver\$sourcefolder" "\\$targetserver\$targetfolder" *.* /r:2 /w:5 /e /purge

 

/purge ask to remove anything at the target that doesn't exists at source. Basically it does a folder sync more than a source folder content copy to the target.

/e copies also empty folders

/r:2 retries twice if copy errors while /w:5 asks to wait 5 second between every try

 

I mostly concerned with the /purge option. I don't see any option in copy-item that would do a sync of the source and target folder. 

 

Do I need to create a function to do it myself or is there any native way of doing it that I'm not aware of?

 

This page suggest that it is not handled by default (see the very last proposal) :
How to keep 2 folders in sync using powershell script - Stack Overflow

 

Thank you.

 

 

1 Reply

@John_Dodo 

Yes, the Copy-Item cmdlet in PowerShell does not have a direct equivalent of the /purge switch available in robocopy. However, you can still achieve the same functionality by combining a few different cmdlets.

One approach is to use Get-ChildItem to get all the files and folders in the source directory, and then pipe them to ForEach-Object where you can use Test-Path to check if each item exists in the target directory. If an item does not exist in the target directory, you can use Copy-Item to copy it from the source directory to the target directory. Finally, you can use Get-ChildItem again on the target directory to get all the items that exist in the target but not in the source, and then pipe them to Remove-Item to delete them.

Here's an example of what the code might look like:

$source = "\\$sourceserver\$sourcefolder"
$target = "\\$targetserver\$targetfolder"

# Copy files and folders that exist in the source but not in the target
Get-ChildItem $source -Recurse | ForEach-Object {
    $targetPath = $_.FullName -replace [regex]::Escape($source), $target
    if (!(Test-Path $targetPath)) {
        Copy-Item $_.FullName -Destination $targetPath -Recurse
    }
}

# Remove files and folders that exist in the target but not in the source
Get-ChildItem $target -Recurse | Where-Object {
    $sourcePath = $_.FullName -replace [regex]::Escape($target), $source
    !(Test-Path $sourcePath)
} | Remove-Item -Recurse

 Note that this example assumes that both the source and target directories exist and are accessible to the user running the script. You may also want to add some error handling and logging to the script to handle any unexpected issues that may arise during the copying and syncing process.