Last active
January 17, 2025 12:03
-
-
Save iamrobert/1524d7e626bb1367b58123eae38eaf17 to your computer and use it in GitHub Desktop.
A PowerShell script to monitor and sync changes between source and destination directories.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Define the project name variable | |
$projectName = "jy" | |
# Define source and destination paths | |
$templateSrc = "D:\2025-laragon\www\$projectName\templates\iamrobert4" | |
$templateDst = "D:\bitbucket\$projectName" | |
$mediaSrc = "D:\2025-laragon\www\$projectName\media\templates\site\iamrobert4" | |
$mediaDst = "D:\bitbucket\$projectName\media\templates\site\iamrobert4" | |
# Function to compare and sync files | |
function Sync-Files { | |
param ( | |
[string]$sourcePath, | |
[string]$destPath, | |
[bool]$isTemplate = $false | |
) | |
# First, remove any unauthorized items from destination | |
Write-Host "Checking for unauthorized items in destination..." -ForegroundColor Yellow | |
if (Test-Path $destPath) { | |
$destItems = Get-ChildItem -Path $destPath -Recurse -Force -ErrorAction SilentlyContinue | |
foreach ($destItem in $destItems) { | |
# Skip .git directory and its contents | |
if ($destItem.FullName -like "*\.git*") { | |
continue | |
} | |
$relativePath = $destItem.FullName.Replace($destPath, "") | |
$sourceItem = Join-Path $sourcePath $relativePath | |
if (!(Test-Path $sourceItem)) { | |
Write-Host "Removing unauthorized item: $($destItem.FullName)" -ForegroundColor Red | |
Remove-Item -Path $destItem.FullName -Force -Recurse | |
} | |
} | |
} | |
# Get all files from source | |
$sourceFiles = Get-ChildItem -Path $sourcePath -Recurse -File | |
foreach ($sourceFile in $sourceFiles) { | |
# Calculate destination path | |
if ($isTemplate) { | |
$relativePath = $sourceFile.FullName.Replace($templateSrc, "") | |
$destFile = Join-Path $templateDst $relativePath | |
} else { | |
$relativePath = $sourceFile.FullName.Replace($mediaSrc, "") | |
$destFile = Join-Path $mediaDst $relativePath | |
} | |
# Check if destination file exists | |
if (Test-Path $destFile) { | |
$destFileInfo = Get-Item $destFile | |
# Compare last write time and size | |
if ($sourceFile.LastWriteTime -ne $destFileInfo.LastWriteTime -or | |
$sourceFile.Length -ne $destFileInfo.Length) { | |
# Files are different, copy the source file | |
Write-Host "Updating: $destFile" -ForegroundColor Yellow | |
$destFolder = Split-Path -Parent $destFile | |
if (!(Test-Path $destFolder)) { | |
New-Item -ItemType Directory -Path $destFolder -Force | Out-Null | |
} | |
Copy-Item -Path $sourceFile.FullName -Destination $destFile -Force | |
} | |
} else { | |
# Destination file doesn't exist, copy it | |
Write-Host "Creating new file: $destFile" -ForegroundColor Green | |
$destFolder = Split-Path -Parent $destFile | |
if (!(Test-Path $destFolder)) { | |
New-Item -ItemType Directory -Path $destFolder -Force | Out-Null | |
} | |
Copy-Item -Path $sourceFile.FullName -Destination $destFile -Force | |
} | |
} | |
} | |
# Perform initial sync | |
Write-Host "Performing initial sync..." -ForegroundColor Cyan | |
Sync-Files -sourcePath $templateSrc -destPath $templateDst -isTemplate $true | |
Sync-Files -sourcePath $mediaSrc -destPath $mediaDst -isTemplate $false | |
Write-Host "Initial sync completed" -ForegroundColor Cyan | |
# Define the action to perform on file changes | |
$action = { | |
# Get the changed item and calculate its destination | |
$changedItem = $Event.SourceEventArgs.FullPath | |
# Different replacement logic for template and media files | |
if ($changedItem.Contains("\templates\iamrobert4")) { | |
# For template files, copy to root | |
$destination = $changedItem -replace [regex]::Escape("D:\2025-laragon\www\$projectName\templates\iamrobert4"), "D:\bitbucket\$projectName" | |
# Re-run sync to clean up unauthorized items | |
Sync-Files -sourcePath $templateSrc -destPath $templateDst -isTemplate $true | |
} else { | |
# For media files, maintain structure | |
$destination = $changedItem -replace [regex]::Escape("D:\2025-laragon\www\$projectName"), "D:\bitbucket\$projectName" | |
# Re-run sync to clean up unauthorized items | |
Sync-Files -sourcePath $mediaSrc -destPath $mediaDst -isTemplate $false | |
} | |
Write-Host "Change detected: $changedItem" -ForegroundColor Yellow | |
# Check if the changed item exists (file or folder) | |
if (Test-Path $changedItem) { | |
# Ensure the parent folder exists at the destination | |
$destinationParent = Split-Path -Parent $destination | |
if (!(Test-Path $destinationParent)) { | |
New-Item -ItemType Directory -Path $destinationParent | Out-Null | |
} | |
# Copy the changed file or folder to the destination | |
Write-Host "Copying $changedItem to $destination" -ForegroundColor Green | |
Copy-Item -Path $changedItem -Destination $destination -Recurse -Force | |
} else { | |
# Handle deleted items | |
if (Test-Path $destination) { | |
Write-Host "Deleting $destination as it no longer exists in source" -ForegroundColor Red | |
Remove-Item -Path $destination -Recurse -Force | |
} else { | |
Write-Host "Item $changedItem no longer exists and was not found in destination" -ForegroundColor DarkYellow | |
} | |
} | |
} | |
# Set up the FileSystemWatcher for the templates folder | |
$templateWatcher = New-Object System.IO.FileSystemWatcher | |
$templateWatcher.Path = $templateSrc | |
$templateWatcher.IncludeSubdirectories = $true | |
$templateWatcher.EnableRaisingEvents = $true | |
# Set up the FileSystemWatcher for the media folder | |
$mediaWatcher = New-Object System.IO.FileSystemWatcher | |
$mediaWatcher.Path = $mediaSrc | |
$mediaWatcher.IncludeSubdirectories = $true | |
$mediaWatcher.EnableRaisingEvents = $true | |
# Register the event handlers for templates | |
Register-ObjectEvent $templateWatcher Changed -Action $action | |
Register-ObjectEvent $templateWatcher Created -Action $action | |
Register-ObjectEvent $templateWatcher Deleted -Action $action | |
Register-ObjectEvent $templateWatcher Renamed -Action $action | |
# Register the event handlers for media | |
Register-ObjectEvent $mediaWatcher Changed -Action $action | |
Register-ObjectEvent $mediaWatcher Created -Action $action | |
Register-ObjectEvent $mediaWatcher Deleted -Action $action | |
Register-ObjectEvent $mediaWatcher Renamed -Action $action | |
# Keep the script running | |
Write-Host "Monitoring folders for changes... Press Ctrl+C to stop." -ForegroundColor Cyan | |
Write-Host "Project being monitored: $projectName" -ForegroundColor Cyan | |
while ($true) { Start-Sleep -Seconds 1 } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment