Last active
December 16, 2015 09:58
-
-
Save PolarbearDK/1ff33fd9f9acc987ddbe to your computer and use it in GitHub Desktop.
Powershell function to syncronize a source forlder to a target folder with options for excluding specific files and/or folders.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Syncronize source folder to target folder | |
.DESCRIPTION | |
Check source folder against target folder, and updates files and folders in target. | |
.PARAMETER SourceFolder | |
The source folder for the syncronization. | |
.PARAMETER TargetFolder | |
The target folder for the syncronization. | |
.PARAMETER ExcludeName | |
One or more names that are excluded from the syncronization (Both source & target) | |
Checked against FileInfo.Name/DirectoryInfo.Name. Wildcards supported. | |
.PARAMETER ExcludePath | |
One or more pathnames that are excluded from the syncronization (Both source & target) | |
Checked against FileInfo.FullName/DirectoryInfo.FullName. Wildcards supported. | |
.PARAMETER NoRemove | |
Do not remove extra files/folders from target not present in source. | |
.EXAMPLE | |
Sync-Folder .\Source .\Target | |
This command syncs Source folder to Target folder | |
.EXAMPLE | |
Sync-Folder -Source c:\Source -Target d:\Target -ExcludeName *.name -ExcludePath *\Target\Log -Verbose | |
This command syncs C:\Source folder to D:\Target folder. | |
Files/folders named *.name are not included in the syncronization. | |
Files/folders with a path ending in \Target\Log are not included in the syncronization. | |
-Verbose list all actions taken. | |
.NOTES | |
Author : Philip Hoppe | |
Requires : PowerShell V4 | |
.LINK | |
https://github.com/PolarbearDK | |
#> | |
param | |
( | |
[parameter(Mandatory=$True)] | |
[alias("Source")] | |
[string]$SourceFolder, | |
[parameter(Mandatory=$True)] | |
[alias("Target")] | |
[string]$TargetFolder, | |
[parameter(Mandatory=$False)] | |
[string[]]$ExcludeName, | |
[parameter(Mandatory=$False)] | |
[string[]]$ExcludePath, | |
[parameter(Mandatory=$False)] | |
[switch]$NoRemove | |
) | |
$ErrorActionPreference = "Stop" | |
function Sync-OneFolder | |
{ | |
param | |
( | |
[parameter(Mandatory=$True)] | |
[string]$syncFromFolder, | |
[parameter(Mandatory=$True)] | |
[string]$syncToFolder | |
) | |
#Write-Verbose "Sync $syncFromFolder to $syncToFolder" | |
if (!(Test-Path -Path $syncToFolder -PathType Container)) | |
{ | |
Write-Verbose "Creating Folder : $($syncToFolder)" | |
New-Item $syncToFolder -ItemType "Directory" > $null | |
} | |
$fromList=Get-ChildItem $syncFromFolder -Exclude $ExcludeName | |
$toList=Get-ChildItem $syncToFolder -Exclude $ExcludeName | |
$SourceFiles=$TargetFiles=@() | |
$syncFromFolders=$syncToFolders=@() | |
$SourceFiles+=$fromList | Where {$_.PSIsContainer -eq $False} | |
$TargetFiles+=$toList | Where {$_.PSIsContainer -eq $False} | |
$syncFromFolders+=$fromList | Where {$_.PSIsContainer -eq $True} | |
$syncToFolders+=$toList | Where {$_.PSIsContainer -eq $True} | |
$missingFiles=Compare-Object $SourceFiles $TargetFiles -Property Name | |
$missingFolders=Compare-Object $syncFromFolders $syncToFolders -Property Name | |
foreach ($missingFile in $missingFiles) { | |
$target = Join-Path $syncToFolder $missingFile.Name | |
if($ExcludePath | Where {$target -like $_}) { | |
Write-Verbose "File excluded by ExcludePath: $target" | |
} else { | |
if($missingFile.SideIndicator -eq "<=") { | |
Write-Verbose "Adding file: $target" | |
[System.IO.FileInfo]$sourceItem = $SourceFiles | Where {$_.Name -eq $missingFile.Name} #| Select-Object -first 1 | |
if(!$sourceitem) {throw "SourceItem is null"} | |
Copy-Item $sourceItem -Destination $target | |
} elseif ($missingFile.SideIndicator="=>") { | |
Write-Verbose "Removing file: $target" | |
if(!$NoRemove) { | |
Remove-Item $target | |
} | |
} | |
} | |
} | |
foreach ($missingFolder in $missingFolders) | |
{ | |
$target = Join-Path $syncToFolder $missingFolder.Name | |
if($ExcludePath | Where {$target -like $_}) { | |
Write-Verbose "Folder excluded by ExcludePath: $target" | |
} else { | |
if ($missingFolder.SideIndicator -eq "=>") | |
{ | |
Write-Verbose "Removing folder: $target" | |
if(!$NoRemove) { | |
Remove-Item $target | |
} | |
} | |
} | |
} | |
foreach ($sourceItem in $SourceFiles) | |
{ | |
$target = Join-Path $syncToFolder $SourceItem.Name | |
if($ExcludePath | Where {$target -like $_}) { | |
Write-Verbose "File copy excluded by ExcludePath: $target" | |
} else { | |
[System.IO.FileInfo]$targetItem = Get-ChildItem $target | |
if ($sourceItem.LastWriteTime -ne $targetItem.LastWriteTime -or $sourceItem.Length -ne $targetItem.Length) { | |
Write-Verbose "Updating file: $target" | |
Copy-Item $sourceItem $targetItem -Force | |
} | |
} | |
} | |
foreach($folder in $syncFromFolders) | |
{ | |
$target = Join-Path $syncToFolder $folder.Name | |
if($ExcludePath | Where {$target -like $_}) { | |
Write-Verbose "Directory sync excluded by ExcludePath: $target" | |
} else { | |
Sync-OneFolder (Join-Path $syncFromFolder $folder.Name) $target | |
} | |
} | |
} | |
Sync-OneFolder ([System.IO.Path]::GetFullPath($SourceFolder)) ([System.IO.Path]::GetFullPath($TargetFolder)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment