Powershell Copy-Item but only copy changed files Powershell Copy-Item but only copy changed files powershell powershell

Powershell Copy-Item but only copy changed files


Both of those are solid answers for powershell, but it would probably be far more easy to just leverage Robocopy (MS Supplied robust copy application).

robocopy "C:\SourceDir\" "C:\DestDir\" /MIR

would accomplish the same thing.


Here is some of the guidelines how you can your script to be more maintainable.

Conver the original script as a filter.

filter HasChanged {     param($file)    # if $file's MD5 has does not exist    # then return $_}

Then simply filter all files that are updated and copy them.

# Note that "Copy-Item" here does not preserve original directory structure# Every updated file gets copied right under "C:\MyTest2"ls C:\MyTest -Recurse | HasChanged | Copy-Item -Path {$_} C:\MyTest2

Or you can create another function that generates sub directory

ls C:\MyTest -Recurse | HasChanged | % { Copy-Item $_ GenerateSubDirectory(...) }


I found a solution...but not sure it is the best from a performance perspective:

$Source = "c:\scripts"$Destination = "c:\test"######################################################################################################Param($Source,$Destination)function Get-FileMD5 {    Param([string]$file)    $mode = [System.IO.FileMode]("open")    $access = [System.IO.FileAccess]("Read")    $md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider    $fs = New-Object System.IO.FileStream($file,$mode,$access)    $Hash = $md5.ComputeHash($fs)    $fs.Close()    [string]$Hash = $Hash    Return $Hash}function Copy-LatestFile{    Param($File1,$File2,[switch]$whatif)    $File1Date = get-Item $File1 | foreach-Object{$_.LastWriteTimeUTC}    $File2Date = get-Item $File2 | foreach-Object{$_.LastWriteTimeUTC}    if($File1Date -gt $File2Date)    {        Write-Host "$File1 is Newer... Copying..."        if($whatif){Copy-Item -path $File1 -dest $File2 -force -whatif}        else{Copy-Item -path $File1 -dest $File2 -force}    }    else    {        #Don't want to copy this in my case..but good to know        #Write-Host "$File2 is Newer... Copying..."        #if($whatif){Copy-Item -path $File2 -dest $File1 -force -whatif}        #else{Copy-Item -path $File2 -dest $File1 -force}    }    Write-Host}# Getting Files/Folders from Source and Destination$SrcEntries = Get-ChildItem $Source -Recurse$DesEntries = Get-ChildItem $Destination -Recurse# Parsing the folders and Files from Collections$Srcfolders = $SrcEntries | Where-Object{$_.PSIsContainer}$SrcFiles = $SrcEntries | Where-Object{!$_.PSIsContainer}$Desfolders = $DesEntries | Where-Object{$_.PSIsContainer}$DesFiles = $DesEntries | Where-Object{!$_.PSIsContainer}# Checking for Folders that are in Source, but not in Destinationforeach($folder in $Srcfolders){    $SrcFolderPath = $source -replace "\\","\\" -replace "\:","\:"    $DesFolder = $folder.Fullname -replace $SrcFolderPath,$Destination    if(!(test-path $DesFolder))    {        Write-Host "Folder $DesFolder Missing. Creating it!"        new-Item $DesFolder -type Directory | out-Null    }}# Checking for Folders that are in Destinatino, but not in Sourceforeach($folder in $Desfolders){    $DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:"    $SrcFolder = $folder.Fullname -replace $DesFilePath,$Source    if(!(test-path $SrcFolder))    {        Write-Host "Folder $SrcFolder Missing. Creating it!"        new-Item $SrcFolder -type Directory | out-Null    }}# Checking for Files that are in the Source, but not in Destinationforeach($entry in $SrcFiles){    $SrcFullname = $entry.fullname    $SrcName = $entry.Name    $SrcFilePath = $Source -replace "\\","\\" -replace "\:","\:"    $DesFile = $SrcFullname -replace $SrcFilePath,$Destination    if(test-Path $Desfile)    {        $SrcMD5 = Get-FileMD5 $SrcFullname        $DesMD5 = Get-FileMD5 $DesFile        If(Compare-Object $srcMD5 $desMD5)        {            Write-Host "The Files MD5's are Different... Checking Write            Dates"            Write-Host $SrcMD5            Write-Host $DesMD5            Copy-LatestFile $SrcFullname $DesFile        }    }    else    {        Write-Host "$Desfile Missing... Copying from $SrcFullname"        copy-Item -path $SrcFullName -dest $DesFile -force    }}# Checking for Files that are in the Destinatino, but not in Sourceforeach($entry in $DesFiles){    $DesFullname = $entry.fullname    $DesName = $entry.Name    $DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:"    $SrcFile = $DesFullname -replace $DesFilePath,$Source    if(!(test-Path $SrcFile))    {        Write-Host "$SrcFile Missing... Copying from $DesFullname"        copy-Item -path $DesFullname -dest $SrcFile -force    }}