Merge folders with Windows PowerShell script
Detect changes and merge folders and files with PowerShell script
When deploying application to specific location it is often required to deploy only few files and not the whole deployment package.
For example, if you changed only single static image file in your ASP.NET WebApplication, there is no reason to overwrite bin folder content and cause WebApplication on IIS to restart.
Similar example can be running Windows Service for which you changed only files excluding executable file which might be running and locked by the running Windows Service process. In case you are replacing all files in the destination folder and therefore restarting the windows service.
Some deployment tools provide these kind of options to replace only different files, but in some cases this is not available, so to avoid scenarios like this or similar we can always rely to PowerShell.
Before we start with the PowerShell script, we need to create some test folders for merging. I created the following two folders named SOURCE and DESTINATION with some dummy file which should represent the live scenario
Hwere you can clearly see the differences between folders. To make it more obvious that we copied only the files that are different or missing, we are going to use a temporaty folder which for this sample I named TEMP.
Param([Parameter(Mandatory=$true)][string]$sourcePath,[Parameter(Mandatory=$true)][string]$destinationPath,[Parameter(Mandatory=$true)][string]$tempPath)if(!$tempPath.EndsWith("\")){$tempPath = $tempPath + "\"}$tmpContent = $tempPath "*"Remove-Item $tmpContent -Recurse -Force$files = Get-ChildItem -Path $sourcePath -Recurse -Filter "*.*"foreach($file in $files){$sourcePathFile = $file.FullName$destinationPathFile = $file.FullName.Replace($sourcePath, $destinationPath)$tempPathFile = $file.FullName.Replace($sourcePath, $tempPath) $exists = Test-Path $destinationPathFile if(!$exists){ $dir = Split-Path -parent $tempPathFile if (!(Test-Path($dir))) { New-Item -ItemType directory -Path $dir } Copy-Item -Path $sourcePathFile -Destination $tempPathFile -Recurse -Force } else{ $isFile = Test-Path -Path $destinationPathFile -PathType Leaf if($isFile){ $different = Compare-Object -ReferenceObject $(Get-Content $sourcePathFile) -DifferenceObject $(Get-Content $destinationPathFile) if(Compare-Object -ReferenceObject $(Get-Content $sourcePathFile) -DifferenceObject $(Get-Content $destinationPathFile)){ $dir = Split-Path -parent $tempPathFile if (!(Test-Path($dir))) { New-Item -ItemType directory -Path $dir } Copy-Item -Path $sourcePathFile -Destination $tempPathFile -Recurse -Force } } } }
Now when we run this script with SOURCE, DESTINATION and TEMP folder full paths we should have only images and templates folder in it as their content is diffrent/missing in the destination folder.
Since we all the changes copied to TEMP folder, we just need to copy them to DESTINATION folder
Copy-Item -Path $tmpContent -Destination $destinationPath -Force -Recurse
We do not actually need TEMP folder, we only used it here to check the files to be copied and to confirm that only differences are copied. We can easily remove all operation with TEMP folder ad do directly copy to DESTINATION folder
Param( [Parameter(Mandatory=$true)] [string]$sourcePath, [Parameter(Mandatory=$true)] [string]$destinationPath ) $files = Get-ChildItem -Path $sourcePath -Recurse -Filter "*.*" foreach($file in $files){ $sourcePathFile = $file.FullName $destinationPathFile = $file.FullName.Replace($sourcePath, $destinationPath) $exists = Test-Path $destinationPathFile if(!$exists){ $dir = Split-Path -parent $destinationPathFile if (!(Test-Path($dir))) { New-Item -ItemType directory -Path $dir } Copy-Item -Path $sourcePathFile -Destination $destinationPathFile -Recurse -Force } else{ $isFile = Test-Path -Path $destinationPathFile -PathType Leaf if($isFile){ $different = Compare-Object -ReferenceObject $(Get-Content $sourcePathFile) -DifferenceObject $(Get-Content $destinationPathFile) if(Compare-Object -ReferenceObject $(Get-Content $sourcePathFile) -DifferenceObject $(Get-Content $destinationPathFile)){ $dir = Split-Path -parent $destinationPathFile if (!(Test-Path($dir))) { New-Item -ItemType directory -Path $dir } Copy-Item -Path $sourcePathFile -Destination $destinationPathFile -Recurse -Force } } } }
References
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article