[CmdletBinding()] param( [switch]$DebugMode ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' function Get-YoungestTimestamp { param( [Parameter(Mandatory)] [string]$FolderPath ) $files = Get-ChildItem -LiteralPath $FolderPath -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notlike '*\_archive\*' } $young = $files | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty LastWriteTime if (-not $young) { return [datetime]::Parse('1900-01-01') } return $young } <<<<<<< HEAD <<<<<<< HEAD ======= ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 function Sync-SequenceFilenames { param( [Parameter(Mandatory)] [string]$SequenceFolderPath, [Parameter(Mandatory)] [string]$SequenceName, [string]$LogFile, [string[]]$Extensions = @('.png','.jpg','.jpeg','.exr','.tif','.tiff','.bmp','.tga') ) $renamed = 0 $collisions = 0 $errors = 0 $checked = 0 if ($LogFile) { "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] RENAME CHECK in '$SequenceFolderPath' (seq='$SequenceName')" | Add-Content -LiteralPath $LogFile } $files = Get-ChildItem -LiteralPath $SequenceFolderPath -File -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notlike '*\_archive\*' -and ($Extensions -contains $_.Extension.ToLower()) } foreach ($f in $files) { $checked++ $base = [System.IO.Path]::GetFileNameWithoutExtension($f.Name) $ext = $f.Extension $digits = $null if ($base -match '_(\d{6})$') { $digits = $Matches[1] } elseif ($base -match '(? '$newName'" | Add-Content -LiteralPath $LogFile } continue } Rename-Item -LiteralPath $f.FullName -NewName $newName -ErrorAction Stop $renamed++ if ($LogFile) { "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] RENAME: '$($f.Name)' -> '$newName'" | Add-Content -LiteralPath $LogFile } } catch { $errors++ if ($LogFile) { "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] RENAME ERROR for '$($f.Name)': $($_.Exception.Message)" | Add-Content -LiteralPath $LogFile } } } return [pscustomobject]@{ Renamed = $renamed Collisions = $collisions Errors = $errors Checked = $checked } } <<<<<<< HEAD >>>>>>> main ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 try { $root = (Get-Location).ProviderPath $currentDir = Join-Path $root '_CURRENT' if (-not (Test-Path -LiteralPath $currentDir)) { New-Item -ItemType Directory -Path $currentDir -Force | Out-Null } <<<<<<< HEAD <<<<<<< HEAD $logFile = Join-Path $currentDir '_UpdateSequences.log' ======= $logFile = Join-Path $currentDir '_UpdateSequences.log' >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences (ps1) started in '$root' ===" | Add-Content -LiteralPath $logFile # Scan for folders with YYYY-MM-DD format (e.g., 2023-12-15) instead of daily_* $dailyDirs = Get-ChildItem -LiteralPath $root -Directory -Filter '????-??-??' | Where-Object { $_.Name -ne '_archive' } $mapDaily = @{} $dailiesScanned = 0 <<<<<<< HEAD ======= $logFile = Join-Path $currentDir '_UpdateSequences.log' "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences (ps1) started in '$root' ===" | Add-Content -LiteralPath $logFile $dailyDirs = Get-ChildItem -LiteralPath $root -Directory -Filter 'daily_*' | Where-Object { $_.Name -ne '_archive' } $mapDaily = @{} $dailiesScanned = 0 $filesRenamedTotal = 0 $renameCollisions = 0 $renameErrors = 0 >>>>>>> main ======= $filesRenamedTotal = 0 $renameCollisions = 0 $renameErrors = 0 >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 foreach ($d in $dailyDirs) { $dailiesScanned++ $seqDirs = @(Get-ChildItem -LiteralPath $d.FullName -Directory | Where-Object { $_.Name -ne '_archive' }) if ($seqDirs.Count -eq 0) { $seqDirs = @($d) } foreach ($s in $seqDirs) { if (-not (Test-Path -LiteralPath $s.FullName)) { continue } <<<<<<< HEAD <<<<<<< HEAD ======= ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 $renameResult = Sync-SequenceFilenames -SequenceFolderPath $s.FullName -SequenceName $s.Name -LogFile $logFile if ($DebugMode -or $renameResult.Renamed -gt 0 -or $renameResult.Collisions -gt 0 -or $renameResult.Errors -gt 0) { Write-Host "[RENAME]|$($s.FullName)|$($s.Name)|checked=$($renameResult.Checked)|renamed=$($renameResult.Renamed)|collisions=$($renameResult.Collisions)|errors=$($renameResult.Errors)" -ForegroundColor Cyan } $filesRenamedTotal += $renameResult.Renamed $renameCollisions += $renameResult.Collisions $renameErrors += $renameResult.Errors <<<<<<< HEAD >>>>>>> main ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 $young = Get-YoungestTimestamp -FolderPath $s.FullName $filesCount = @(Get-ChildItem -LiteralPath $s.FullName -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notlike '*\_archive\*' }).Count $seqName = $s.Name $cand = [pscustomobject]@{ Seq = $seqName SrcFull = $s.FullName Young = $young FilesCount = $filesCount } if ($mapDaily.ContainsKey($seqName)) { if ($mapDaily[$seqName].Young -lt $young) { $mapDaily[$seqName] = $cand } } else { $mapDaily[$seqName] = $cand } } } $mapCurrent = @{} if (Test-Path -LiteralPath $currentDir) { foreach ($c in Get-ChildItem -LiteralPath $currentDir -Directory | Where-Object { $_.Name -ne '_archive' }) { $mapCurrent[$c.Name] = Get-YoungestTimestamp -FolderPath $c.FullName } } $lines = @() $lines += "[MAPCOUNT]|count=$($mapDaily.Count)" $total = 0 $toCopy = 0 foreach ($k in $mapDaily.Keys) { $total++ $d = $mapDaily[$k] $curYoung = if ($mapCurrent.ContainsKey($k)) { $mapCurrent[$k] } else { [datetime]::Parse('1900-01-01') } if ($d.Young -gt $curYoung) { $toCopy++ $lines += "[COPY]|$($d.SrcFull)|$($d.Seq)|files=$($d.FilesCount)|young=$($d.Young.ToString('s'))" } else { $lines += "[SKIP]|$($d.SrcFull)|$($d.Seq)|reason=notNewer|srcYoung=$($d.Young.ToString('s'))|curYoung=$($curYoung.ToString('s'))" } } <<<<<<< HEAD <<<<<<< HEAD $lines += "[META]|dailiesScanned=$dailiesScanned|sequencesTotal=$total|toCopy=$toCopy" # Print plan to console instead of writing to file Write-Host "=== UPDATE PLAN ===" -ForegroundColor Cyan foreach ($line in $lines) { if ($line -like '[COPY]*') { Write-Host $line -ForegroundColor Green } elseif ($line -like '[SKIP]*') { Write-Host $line -ForegroundColor Yellow } else { Write-Host $line -ForegroundColor White } } Write-Host "==================" -ForegroundColor Cyan ======= $lines += "[META]|dailiesScanned=$dailiesScanned|sequencesTotal=$total|toCopy=$toCopy" ======= $lines += "[META]|dailiesScanned=$dailiesScanned|sequencesTotal=$total|toCopy=$toCopy" >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 # Print plan to console instead of writing to file Write-Host "=== UPDATE PLAN ===" -ForegroundColor Cyan foreach ($line in $lines) { if ($line -like '[COPY]*') { Write-Host $line -ForegroundColor Green } elseif ($line -like '[SKIP]*') { Write-Host $line -ForegroundColor Yellow } else { Write-Host $line -ForegroundColor White } } Write-Host "==================" -ForegroundColor Cyan <<<<<<< HEAD >>>>>>> main ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 $sequencesMirrored = 0 $mirrorFailures = 0 foreach ($line in $lines) { if ($line.StartsWith('[COPY]')) { $parts = $line -split '\|' $srcFull = $parts[1] $seqName = $parts[2] $dstAbs = Join-Path $currentDir $seqName <<<<<<< HEAD if (-not (Test-Path -LiteralPath $dstAbs)) { New-Item -ItemType Directory -Path $dstAbs -Force | Out-Null } "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] Mirror: '$srcFull' -> '$dstAbs'" | Add-Content -LiteralPath $logFile <<<<<<< HEAD $args = @( ======= if (Test-Path -LiteralPath $dstAbs) { "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] WIPE: removing existing destination '$dstAbs'" | Add-Content -LiteralPath $logFile try { Remove-Item -LiteralPath $dstAbs -Recurse -Force -ErrorAction Stop } catch { "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] WIPE ERROR: $($_.Exception.Message)" | Add-Content -LiteralPath $logFile } } if (-not (Test-Path -LiteralPath $dstAbs)) { New-Item -ItemType Directory -Path $dstAbs -Force | Out-Null } "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] Mirror: '$srcFull' -> '$dstAbs'" | Add-Content -LiteralPath $logFile $robocopyArgs = @( >>>>>>> main ======= $robocopyArgs = @( >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 $srcFull, $dstAbs, '/MIR','/MT:8','/R:1','/W:1','/COPY:DAT','/DCOPY:DAT','/FFT','/NFL','/NDL','/NP','/NJH','/NJS','/XD','_archive' ) <<<<<<< HEAD <<<<<<< HEAD $null = & robocopy @args 2>&1 | Add-Content -LiteralPath $logFile ======= $null = & robocopy @robocopyArgs 2>&1 | Add-Content -LiteralPath $logFile >>>>>>> main ======= $null = & robocopy @robocopyArgs 2>&1 | Add-Content -LiteralPath $logFile >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 $rc = $LASTEXITCODE if ($rc -lt 8) { $sequencesMirrored++ "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] OK rc=$rc" | Add-Content -LiteralPath $logFile } else { $mirrorFailures++ "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] ERROR rc=$rc" | Add-Content -LiteralPath $logFile } } } <<<<<<< HEAD <<<<<<< HEAD # Print summary report to console Write-Host "=== SUMMARY REPORT ===" -ForegroundColor Magenta Write-Host "Dailies scanned: $dailiesScanned" -ForegroundColor White Write-Host "Sequences found: $total" -ForegroundColor White Write-Host "Planned copies: $toCopy" -ForegroundColor Green Write-Host "Completed OK: $sequencesMirrored" -ForegroundColor Green Write-Host "Completed FAIL: $mirrorFailures" -ForegroundColor Red ======= # Print summary report to console Write-Host "=== SUMMARY REPORT ===" -ForegroundColor Magenta Write-Host "Dailies scanned: $dailiesScanned" -ForegroundColor White Write-Host "Sequences found: $total" -ForegroundColor White Write-Host "Planned copies: $toCopy" -ForegroundColor Green Write-Host "Completed OK: $sequencesMirrored" -ForegroundColor Green Write-Host "Completed FAIL: $mirrorFailures" -ForegroundColor Red Write-Host "Files renamed: $filesRenamedTotal (collisions: $renameCollisions, errors: $renameErrors)" -ForegroundColor White >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 # Summarize skipped sequences $skippedLines = @() foreach ($line in $lines) { if ($line.StartsWith('[SKIP]')) { $skippedLines += $line } } if ($skippedLines.Count -gt 0) { Write-Host "`n=== SKIPPED SEQUENCES ===" -ForegroundColor Yellow $skippedByReason = @{} foreach ($skip in $skippedLines) { $parts = $skip -split '\|' $reason = $parts[3] $seqName = $parts[2] if (-not $skippedByReason.ContainsKey($reason)) { $skippedByReason[$reason] = @() } $skippedByReason[$reason] += $seqName } foreach ($reason in $skippedByReason.Keys) { $seqs = $skippedByReason[$reason] Write-Host "$reason ($($seqs.Count) sequences):" -ForegroundColor Yellow foreach ($seq in $seqs | Sort-Object) { Write-Host " - $seq" -ForegroundColor White } } Write-Host "========================" -ForegroundColor Yellow } Write-Host "=====================" -ForegroundColor Magenta "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences (ps1) completed (d=$dailiesScanned seq=$total ok=$sequencesMirrored fail=$mirrorFailures) ===" | Add-Content -LiteralPath $logFile <<<<<<< HEAD Write-Host "@$logFile" ======= # Print summary report to console Write-Host "=== SUMMARY REPORT ===" -ForegroundColor Magenta Write-Host "Dailies scanned: $dailiesScanned" -ForegroundColor White Write-Host "Sequences found: $total" -ForegroundColor White Write-Host "Planned copies: $toCopy" -ForegroundColor Green Write-Host "Completed OK: $sequencesMirrored" -ForegroundColor Green Write-Host "Completed FAIL: $mirrorFailures" -ForegroundColor Red Write-Host "Files renamed: $filesRenamedTotal (collisions: $renameCollisions, errors: $renameErrors)" -ForegroundColor White # Summarize skipped sequences $skippedLines = @() foreach ($line in $lines) { if ($line.StartsWith('[SKIP]')) { $skippedLines += $line } } if ($skippedLines.Count -gt 0) { Write-Host "`n=== SKIPPED SEQUENCES ===" -ForegroundColor Yellow $skippedByReason = @{} foreach ($skip in $skippedLines) { $parts = $skip -split '\|' $reason = $parts[3] $seqName = $parts[2] if (-not $skippedByReason.ContainsKey($reason)) { $skippedByReason[$reason] = @() } $skippedByReason[$reason] += $seqName } foreach ($reason in $skippedByReason.Keys) { $seqs = $skippedByReason[$reason] Write-Host "$reason ($($seqs.Count) sequences):" -ForegroundColor Yellow foreach ($seq in $seqs | Sort-Object) { Write-Host " - $seq" -ForegroundColor White } } Write-Host "========================" -ForegroundColor Yellow } Write-Host "=====================" -ForegroundColor Magenta "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] === UpdateSequences (ps1) completed (d=$dailiesScanned seq=$total ok=$sequencesMirrored fail=$mirrorFailures) ===" | Add-Content -LiteralPath $logFile Write-Host "@$logFile" >>>>>>> main ======= Write-Host "@$logFile" >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37 exit 0 } catch { $root = (Get-Location).ProviderPath $currentDir = Join-Path $root '_CURRENT' if (-not (Test-Path -LiteralPath $currentDir)) { New-Item -ItemType Directory -Path $currentDir -Force | Out-Null } $planFile = Join-Path $currentDir '_UpdatePlan.txt' ($_.Exception | Out-String) | Set-Content -LiteralPath ($planFile + '.error.txt') -Encoding ASCII Write-Host "ERROR: $_" exit 1 } <<<<<<< HEAD <<<<<<< HEAD ======= >>>>>>> main ======= >>>>>>> d89d8e0cf215637d0ffabf165877815ab4203f37