Hi. Here’s another update on the Sync-Folder script. The script itself is at that link but in this post I go over the changes I made and how they work.
The main addition is the support for -WhatIf (so you can test the script runs without it making changes). In addition I fixed some odd bugs with the Filter and Exceptions parameters. Plus some more Verbose logging and I tidied up the script a bit (removing some of the cmdlet aliases and replacing them with the full commands).
Fixing the Filter parameter was first. That involved changing the following lines;
$CurrentFilter="*"
and later;
If(Get-PropertyExists -Queryobject $Pair -PropertyName Filter) { if (($Pair.Filter -ne $Null) -and ($Pair.Filter -ne "")) { $CurrentFilter=$Pair.Filter } }
The problem here was the first version checked to see if the Filter property existed in the configuration file and if it did, used it as the Filter. But if the property existing AND was empty, then the empty Filter was used instead. The above change makes sure the file Filter only overwrites the default “*” (syncing everything) if there’s something in it.
Also, one of the recursive calls to Sync-OneFolder didn’t pass on the Filter correctly.
Another error in the Exception and Filter processing was fixed by making the following change;
Return (($Queryobject | Get-Member -MemberType Property | Select-Object -ExpandProperty Name) -contains $PropertyName)
In the original version, it just checked the properties of the XML object passed (to make sure something was in there). But as it was being compared to a String ($PropertyName) sometimes the comparison failed. So I added the Select-Object part above to get the Name of the Property to make sure it compared correctly to $PropertyName.
Adding WhatIf should have been reasonably straight forward; just add -WhatIf:$WhatIf to each cmdlet so the status of WhatIf passed to the function is given to each.
That broke a few things though, mainly;
if ($SourceFile.LastWriteTime -gt ((Get-ChildItem -LiteralPath ($TargetFolder+"\"+$SourceFile.Name)).LastWriteTime))
This was from the code that updates files when the source data is newer than the version on the target. It relies on the target path existing though which if you’re running WhatIf, it won’t in all cases (as the script won’t create the parent directories).
So I swapped it around a bit;
$MatchingSourceFile= $SourceFiles | Where-Object {$_.Name -eq $TargetFiles.Name} If ($MatchingSourceFile -ne $Null) { If ($MatchingSourceFile.LastWriteTime -gt $TargetFile.LastWriteTime)
This uses the target and derives the source from that (rather than the other way around). That means only existing targets will be processed, ie where the target files were there already and we need to check if there’s a newer source version.
A similar change was needed here;
$SourceFiles=$TargetFiles=$TargetList=@() $SourceFolders=$TargetFolders=@() $SourceList=Get-ChildItem -LiteralPath $SourceFolder if (Test-Path $TargetFolder) { $TargetList=Get-ChildItem -LiteralPath $TargetFolder }
The script creates missing folders right at the start. If WhatIf is specified those missing folders in the target are not created. So this code now checks that $TargetFolder exists otherwise $TargetList is created as empty (so the script doesn’t do anything).