-
-
Save lafleurh/a3877a8604758892637c3612f76bc0e3 to your computer and use it in GitHub Desktop.
| Param ( | |
| [string]$LeftFolder, | |
| [string]$RightFolder | |
| ) | |
| function CreateFolderStructure([string]$Path) | |
| { | |
| if (-not [string]::IsNullOrWhiteSpace($Path)) | |
| { | |
| if (-not (Test-Path $Path)) | |
| { | |
| $ParentPath = Split-Path $Path -Parent | |
| CreateFolderStructure -Path $ParentPath | |
| New-Item -Path $Path -ItemType Directory | |
| } | |
| } | |
| } | |
| function SyncFolders([string]$FldrL, [string]$FldrR) | |
| { | |
| Write-Host "Preparing to copy $($FldrL) to $($FldrR)" | |
| $LeftItems = Get-ChildItem -Recurse -Path $FldrL | |
| $RightItems = Get-ChildItem -Recurse -Path $FldrR | |
| $Result = Compare-Object -ReferenceObject $LeftItems -DifferenceObject $RightItems -IncludeEqual | |
| foreach ($Folder in $Result) { | |
| $CopyFile = $false | |
| $CopyLeft = $false | |
| $CopyRight = $false | |
| if ($Folder.SideIndicator -eq "==") | |
| { | |
| $LeftPath = $Folder.InputObject.FullName | |
| $RightPath = $Folder.InputObject.FullName.Replace($FldrL, $FldrR) | |
| if (Test-Path $LeftPath) | |
| { | |
| if (Test-Path $RightPath) | |
| { | |
| $LeftDate = [datetime](Get-ItemProperty -Path $LeftPath -Name LastWriteTime).LastWriteTime | |
| $RightDate = [datetime](Get-ItemProperty -Path $RightPath -Name LastWriteTime).LastWriteTime | |
| if ((Get-Item $LeftPath).GetType().Name -eq "FileInfo") | |
| { | |
| if ($LeftDate -gt $RightDate) | |
| { | |
| $SourcePath = $LeftPath | |
| $TargetPath = $RightPath | |
| $CopyFile = $true | |
| } | |
| if ($RightDate -gt $LeftDate) | |
| { | |
| $SourcePath = $RightPath | |
| $TargetPath = $LeftPath | |
| $CopyFile = $true | |
| } | |
| } | |
| } else { | |
| $CopyLeft = $true | |
| } | |
| } else { | |
| if (Test-Path $RightPath) | |
| { | |
| $CopyRight = $true | |
| } | |
| } | |
| } | |
| if ($Folder.SideIndicator -eq "<=" -or $CopyLeft) { | |
| $SourcePath = $Folder.InputObject.FullName | |
| $TargetPath = $Folder.InputObject.FullName.Replace($FldrL, $FldrR) | |
| $CopyFile = $true | |
| } | |
| if ($Folder.SideIndicator -eq "=>" -or $CopyRight) { | |
| $SourcePath = $Folder.InputObject.FullName | |
| $TargetPath = $Folder.InputObject.FullName.Replace($FldrR, $FldrL) | |
| $CopyFile = $true | |
| } | |
| if ($CopyFile -And (Test-Path $SourcePath)) | |
| { | |
| Write-Host "$($Folder.SideIndicator) Copying $($SourcePath) to $($TargetPath)" | |
| $ParentPath = Split-Path $TargetPath -Parent | |
| CreateFolderStructure -Path $ParentPath | |
| if ((Get-Item $SourcePath).GetType().Name -eq "DirectoryInfo") | |
| { | |
| New-Item -Path $TargetPath -ItemType Directory | |
| } | |
| else | |
| { | |
| Copy-Item -Path $SourcePath -Destination $TargetPath | |
| } | |
| } | |
| } | |
| } | |
| SyncFolders -FldrL (Get-Item -Path $LeftFolder).FullName -FldrR (Get-Item -Path $RightFolder).FullName |
In "<=" and '=>"you have to check the LastWriteTime other wise it will be wrong
In "<=" and '=>"you have to check the LastWriteTime other wise it will be wrong
When you see <= or =>, it means that the file is in one folder but not the other, so the action is to copy it to where it is missing.
Thanks so much for this script ! I've been scouring the Internet for something like this for the last hour, and now I find this wonderful piece of code ! Thanks 🙏🏼
@Silloky yes, it has a few issues that I never finished troubleshooting, but I used it quite a bit for even large folders. I think it's because your a and b have the same parent folder. I wrote this for copying across a network, so try much different paths.
@Silloky Fixed the issue and also fixed the recursion creating folders which was inefficient. I've learned a lot about PowerShell since I wrote this a long time ago.
Great, thanks ! But I might try to code something similar to this myself for learning purposes...

You just do:
PS > SyncFolders.ps1 C:\temp C:\temp2
And it will make C:\temp and C:\temp2 the same.
There may be a residual bug or two in this script.