Param( [Parameter(Mandatory = $true)] [string]$Source, [Parameter(Mandatory = $true)] [string]$Destination, [int]$BufferSizeMB = 4, [string]$MoveFiles = "false" ) $shouldMove = $false if ($MoveFiles.ToLower() -eq "true") { $shouldMove = $true } #HASH function Get-FileHashSHA256 { param([string]$Path) return (Get-FileHash -Algorithm SHA256 -Path $Path).Hash } # Format: YYYY-MM-DD_HH-MM-SS for cross-platform friendliness $timestamp = (Get-Date -Format "yyyy-MM-dd_HH-mm-ss") $logFileName = "HashMismatchLog_$timestamp.txt" $logFilePath = Join-Path $Destination $logFileName # Create an empty file to start with New-Item -ItemType File -Path $logFilePath -Force | Out-Null # Prepare buffer size in bytes $bufferSize = $BufferSizeMB * 1MB # Gather all files $files = Get-ChildItem -Path $Source -Recurse -File $totalCount = $files.Count if ($totalCount -eq 0) { Write-Host "No files found under $Source" exit } $currentIndex = 0 foreach ($file in $files) { $currentIndex++ $relative = $file.FullName.Substring($Source.Length).TrimStart('\') $destFull = Join-Path $Destination $relative $destDir = Split-Path $destFull -Parent if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null } $bytesCopied = 0 $fileSize = $file.Length $reader = [System.IO.File]::OpenRead($file.FullName) $writer = [System.IO.File]::Create($destFull) try { $buffer = New-Object byte[] ($BufferSizeMB * 1MB) while (($read = $reader.Read($buffer, 0, $buffer.Length)) -gt 0) { $writer.Write($buffer, 0, $read) $bytesCopied += $read $percentFile = [math]::Round(($bytesCopied / $fileSize) * 100, 1) $percentOverall = [math]::Round(($currentIndex / $totalCount) * 100, 1) Write-Progress ` -Activity "Copying file $currentIndex of $totalCount" ` -Status "$percentFile%% of $($file.Name)" ` -PercentComplete $percentOverall } } finally { $reader.Close() $writer.Close() } # Verify hash match $srcHash = Get-FileHashSHA256 -Path $file.FullName $dstHash = Get-FileHashSHA256 -Path $destFull if ($srcHash -eq $dstHash) { Write-Host "✅ Verified: $relative" if ($shouldMove) { try { Remove-Item $file.FullName -Force Write-Host "🗑️ Moved (source deleted): $relative" } catch { Write-Warning "⚠️ Failed to delete source file: $relative" } } else { Write-Host "Copied: $relative" } } else { Write-Warning "❌ Hash mismatch for $relative — file NOT deleted!" $logEntry = @" SOURCE: $($file.FullName) DEST: $destFull "@ Add-Content -Path $logFilePath -Value $logEntry } } # Finalize progress Write-Progress -Activity "Copy Complete" -Completed Write-Host "All $totalCount files copied from `"$Source`" to `"$Destination`"." if ((Get-Content $logFilePath).Length -eq 0) { Remove-Item $logFilePath -Force Write-Host "✅ No hash mismatches detected — log file auto-deleted." } else { Write-Host "⚠ Hash mismatches logged in: $logFilePath" }