Skip to content

Instantly share code, notes, and snippets.

@PolarbearDK
Last active December 16, 2015 09:58
Show Gist options
  • Save PolarbearDK/1ff33fd9f9acc987ddbe to your computer and use it in GitHub Desktop.
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.
<#
.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