Skip to content

Instantly share code, notes, and snippets.

@WoLfulus
Created April 26, 2025 20:54
Show Gist options
  • Save WoLfulus/194c5b2ecf12320671718132edf13479 to your computer and use it in GitHub Desktop.
Save WoLfulus/194c5b2ecf12320671718132edf13479 to your computer and use it in GitHub Desktop.
#
# Watch for changes
#
function watch {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$Watch,
[Parameter(Mandatory = $true)]
[scriptblock]$Action
)
function Resolve-GlobPattern {
param (
[string]$Pattern
)
$isGlob = $Pattern -match '[*?]'
if (-not $isGlob) {
return @($Pattern)
}
$isRecursive = $Pattern -match '\*\*'
if (-not $isRecursive) {
$items = Get-ChildItem $Pattern -File -ErrorAction SilentlyContinue
return $items
}
$items = Get-ChildItem $Pattern -Recurse -ErrorAction SilentlyContinue | %{ $_.FullName }
return @($items);
}
$filesToWatch = @()
foreach ($pattern in $Watch) {
$resolvedFiles = Resolve-GlobPattern -Pattern $pattern
$filesToWatch += $resolvedFiles
}
$filesToWatch = $filesToWatch | Select-Object -Unique
Write-Host "Watching $($filesToWatch.Count) files for changes..." -ForegroundColor Cyan
$filesToWatch | ForEach-Object { Write-Host " - $_" -ForegroundColor Cyan }
Write-Host ""
# Keep track of last write times
$lastWriteTimes = @{}
$filesToWatch | ForEach-Object {
if (Test-Path -Path $_) {
$lastWriteTimes[$_] = (Get-Item -Path $_).LastWriteTime
}
}
# First execution
$executionScope = New-Module -ScriptBlock {
param($scriptBlock, $filesToWatch)
$global:ChangedFiles = $filesToWatch
& $scriptBlock
Remove-Variable -Name ChangedFiles -Scope Global -ErrorAction SilentlyContinue
} -ArgumentList $Action, $filesToWatch
Write-Host ""
try {
while ($true) {
$changedFiles = @()
foreach ($file in $filesToWatch) {
if (Test-Path -Path $file) {
$currentWriteTime = (Get-Item -Path $file).LastWriteTime
if ($lastWriteTimes.ContainsKey($file) -and $currentWriteTime -gt $lastWriteTimes[$file]) {
$changedFiles += $file
$lastWriteTimes[$file] = $currentWriteTime
}
elseif (-not $lastWriteTimes.ContainsKey($file)) {
$changedFiles += $file
$lastWriteTimes[$file] = $currentWriteTime
}
}
elseif ($lastWriteTimes.ContainsKey($file)) {
$changedFiles += $file
$lastWriteTimes.Remove($file)
}
}
# If files have changed, execute the action
if ($changedFiles.Count -gt 0) {
Clear-Host
Write-Host "`nChanges detected in $($changedFiles.Count) files:" -ForegroundColor Yellow
$changedFiles | ForEach-Object { Write-Host " - $_" -ForegroundColor Yellow }
Write-Host ""
$executionScope = New-Module -ScriptBlock {
param($scriptBlock, $changedFiles)
$global:ChangedFiles = $changedFiles
& $scriptBlock
Remove-Variable -Name ChangedFiles -Scope Global -ErrorAction SilentlyContinue
} -ArgumentList $Action, $changedFiles
Write-Host ""
}
# Check for new files that match the patterns
$newFilesToWatch = @()
foreach ($pattern in $Watch) {
$resolvedFiles = Resolve-GlobPattern -Pattern $pattern
$newFilesToWatch += $resolvedFiles
}
$newFilesToWatch = $newFilesToWatch | Select-Object -Unique
# Add new files to watch list
foreach ($file in $newFilesToWatch) {
if (-not $filesToWatch.Contains($file)) {
$filesToWatch += $file
if (Test-Path -Path $file) {
$lastWriteTimes[$file] = (Get-Item -Path $file).LastWriteTime
}
Write-Host "Now watching new file: $file" -ForegroundColor Cyan
}
}
Start-Sleep -Milliseconds 1000
}
}
catch {
Write-Error "Error in watch function: $_"
}
finally {
Write-Host "Watch stopped." -ForegroundColor Cyan
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment