Wednesday, 23 October 2013

Powershell File Watcher

Ok so today I had a situation where I needed a simple script to copy some website related artifacts to an output directory that would allow me to view the changes on a website. Now during this process I was making a lot of changes over time and wanted to automate the process.

PowerShell to the rescue.

The script below is fairly simple(and a little unrefined), but it does the job nicely. The script will continue to run until you press a key, at which point it will de-register all of its events and exit

The configurable parts are:

  • You can set the folder to watch with the $inputFolder variable
  • You can set the folder to copy changes to with the $outputFolder variable
  • You can set the extensions of the files that you want to copy with the $filters variable

$inputFolder = Resolve-Path '..\inputDirectory'
$outputFolder = Resolve-Path '..\outputDirectory'
$filters = @('*.css', '*.js', '*.html') 

$messageData = "$inputFolder|$outputFolder"


function RegisterWatcher($fileFilter)
{
    $fsw = New-Object IO.FileSystemWatcher $inputFolder, $fileFilter -Property @{IncludeSubdirectories = $true;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 
     
    Register-ObjectEvent $fsw Changed -SourceIdentifier "FileChanged - $fileFilter" -MessageData $messageData -Action { 
        $sourceItem = $Event.SourceEventArgs.FullPath 
        $targetItem = $sourceItem.Replace($Event.MessageData.Split('|')[0], $Event.MessageData.Split('|')[1])

        Copy-Item $sourceItem $targetItem

        Write-Host "Copied $sourceItem"
    } 
}
 
foreach($filter in $filters)
{   
    RegisterWatcher $filter
}

Write-Host "Press any key to exit"

while ($true) {
    if ($Host.UI.RawUI.KeyAvailable) {
        break;
    }
    Start-Sleep -m 1000
}

foreach($filter in $filters)
{
    Unregister-Event "FileChanged - $filter"
}