Skip to content

Instantly share code, notes, and snippets.

@lafleurh
Last active Sep 19, 2021
Embed
What would you like to do?
PowerShell script to do a two-way sync of Windows folders
Param (
[string]$LeftFolder,
[string]$RightFolder
)
function CreateFolderStructure([string]$Path)
{
if (-not [string]::IsNullOrWhiteSpace($Path))
{
$ParentPath = Split-Path $Path -Parent
CreateFolderStructure -Path $ParentPath
if (-not (Test-Path $Path))
{
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)"
CreateFolderStructure -Path $TargetPath
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
@lafleurh
Copy link
Author

lafleurh commented Aug 18, 2019

Fixed issue creating parent folders. Need to recursively create parent folders before creating files in a child folder.

Also, try this for long file name issues (this worked for me on Windows 10):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001

Loading

@johnlee2019
Copy link

johnlee2019 commented Jun 30, 2020

Hi,
Can i know the sample of setting folder path?

Loading

@lafleurh
Copy link
Author

lafleurh commented Jul 2, 2020

Hi,
Can i know the sample of setting folder path?

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.

Loading

@GayanSandaruwan
Copy link

GayanSandaruwan commented Sep 19, 2021

In "<=" and '=>"you have to check the LastWriteTime other wise it will be wrong

Loading

@lafleurh
Copy link
Author

lafleurh commented Sep 19, 2021

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.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment