cmiscloni
cmiscloni

Reputation: 53

Powershell compare-object

I trying to make a script which compare two directory ( source, destination) and if there are a difference on destination, copy files from source to destination. The problem is that I don't know how copy the tree of files too.

Example:

$s = "C:\source\client"
$t = "C:\destination\client"

$target = Get-ChildItem $t -Recurse
$source = get-childitem $s -Recurse
Compare-Object $source $target -Property Name , Length |
    Where-Object { $_.SideIndicator -eq '<=' } |
    foreach-object -process{
        copy-item $_.FullName -destination $t
}

If I have a file in source ( C:\source\client\bin\file.txt) and not in the destination folder, how is the code to copy the file in C:\destination\client\bin\file.txt ?

Thanks.

Upvotes: 0

Views: 2419

Answers (3)

Harry Hung
Harry Hung

Reputation: 111

Thanks for sharing. Here is what I have done with everything I searched to compare MD5 and then copy only newly added and different files.

With [Compare contents of two folders using PowerShell Get-FileHash] from http://almoselhy.azurewebsites.net/2014/12/compare-contents-of-two-folders-using-powershell-get-filehash/

$LeftFolder = "D:\YFMS_Target"
$RightFolder = "D:\YFMS_Copy"
$LeftSideHash = @(Get-ChildItem $LeftFolder -Recurse | Get-FileHash -Algorithm MD5| select @{Label="Path";Expression={$_.Path.Replace($LeftFolder,"")}},Hash)
$RightSideHash = @(Get-ChildItem $RightFolder -Recurse | Get-FileHash -Algorithm MD5| select @{Label="Path";Expression={$_.Path.Replace($RightFolder,"")}},Hash)
robocopy $LeftFolder $RightFolder /e /xf *
Write-Host "robocopy LastExitCode: $LastExitCode"
if ($LastExitCode -gt 7) { exit $LastExitCode } else { $global:LastExitCode = $null }
Compare-Object $LeftSideHash $RightSideHash -Property Path,Hash | Where-Object { $_.SideIndicator -eq '<=' } | foreach { Copy-Item -LiteralPath (Join-Path $LeftFolder $_.Path) -Destination (Join-Path $RightFolder $_.Path) -verbose}

Upvotes: 1

Matt
Matt

Reputation: 46730

I am in the process of testing this more. From what i can see the logic of your code is sound.

Compare-Object $source $target -Property Name , Length |
    Where-Object { $_.SideIndicator -eq '<=' } | Select-Object -ExpandProperty inputobject |
    foreach-object -process{
        copy-item $_.FullName -destination $t
}

Once you have the compare done pipe the results after the Where in Select-Object -ExpandProperty inputobject to extract the File item so that you can see the FullName property

Upvotes: 2

Noah Sparks
Noah Sparks

Reputation: 1772

copy-item has a -recurse parameter that will let you specify the root of a directory and then copy everything below it

copy-item c:\test d:\test -recurse -force

Edit: The problem is for repeated tasks you can't stop it from trying to overwrite everything. You can add -force to make it do it, but it is not very efficient.

Alternatively (and probably a better and simpler way to go about this) you could call robocopy with the /mir switch

Upvotes: 1

Related Questions