PowerShell: Synchronizing a Folder (and Sub-Folders) Part 7

Hi. Here’s another update on the Sync-Folder script.  In this update Strict mode goes on, I make sure the statistics reset between runs, the Statistics output is rewritten and I add the option to only sync items that match a $Filter.

Update : I’ve revisited this script a few times with new additions and modifications.The latest full version of the script is here.  That post also includes links covering the other revisions to the script.The first change was nice and easy;


This resets the statistics between each run of the script.

Catching that bug reminded me to add this to the start of the script though;

set-strictmode -version Latest

This ensures that any variables that are used in the script have to be declared first.  It doesn’t help with the running of the script normally but makes bugs like the above less likely!

Next I optimised how it generates the statistics it displays at the end;

Foreach ($Change in $Changes)
    switch ($Change.Process)
        "Create Folder"{$FolderCreations+=1}
        "Copy File"{$FileCopies+=1}
        "Remove File"{$FileRemovals+=1}
        "Remove Folder"{$FolderRemovals+=1}
        "Update File"{$FileUpdates+=1}
Write-Host "`nStatistics`n"
Write-Host "Folder Creations: `t$FolderCreations"
Write-Host "Folder Removals: `t$FolderRemovals"
Write-Host "File Copies: `t`t$FileCopies"
Write-Host "File Removals: `t`t$FileRemovals"
Write-Host "File Updates: `t`t$FileUpdates`n"

In the previous script version it would loop for each statistic, going through every item in $Changes finding the matching attribute.  With this update it only loops once through all the changes (instead of five times);  much more efficient.

While I was there I added some tabs to the output (“`t“) so the statistics line up nicely.

The final update was adding the ability to only sync files that match a given filter.

First, I need to add the parameter to the main Sync-OneFolder function;


The logic needed a small update too;

    $SourceFiles+=$SourceList | ? {$_.PSIsContainer -eq $False -and $_.FullName -like $Filter -and
         !(Check-Exceptions $_.FullName $PassedExceptions)}
    $TargetFiles+=$TargetList | ? {$_.PSIsContainer -eq $False -and $_.FullName -like $Filter -and
         !(Check-Exceptions $_.FullName $PassedExceptions)}

So an additional -and clause was added to make sure the FullName matches the $Filter.

Finally I need to add the Filter switch to where the main function is called;

if ($PSBoundParameters.ContainsKey("SourceFolder"))
    Write-Verbose "Syncing folder pair passed as parameters."
    Sync-OneFolder -SourceFolder $SourceFolder -TargetFolder $TargetFolder -PassedExceptions $Exceptions -Filter $Filter | 
        Tee-Object -Variable Changes
    Write-Verbose "Running with Configuration File : $ConfigurationFile"
    $Config=[xml](Get-Content $ConfigurationFile)
    foreach ($Pair in $Config.Configuration.SyncPair)
        Write-verbose "Processing Pair"
        Sync-OneFolder -SourceFolder $Pair.Source -TargetFolder $Pair.Target -PassedExceptions $Pair.ExceptionList.Exception -Filter $Pair.Filter |
             Tee-Object -Variable Changes

I updated the default XML that is imported from the config file to include the Filter tag;


So you can call the function with a configuration XML or via the command line switches.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s