Recently I came across a requirement where we wanted to make sure if checksum of files copied from source to destination remain same. Checksum is used data integrity monitoring for given file. I used MD5 checksum algorithm for file integrity check. Refer here for more information.
Manually comparing a large set of files is very inefficient for any System Administrator. I wanted to develop a script that will run on both source and destination files and generate html report showing checksum comparison.
I developed following powershell script to meet above requirements. Hope this will helpful!
Let me know if you face any issue while using this script at your place!
$erroractionpreference = "SilentlyContinue"
try{stop-transcript|out-null}
catch [System.InvalidOperationException]{}
$oPath = "$env:SystemRoot\Temp"
$rPath = "$oPath\CheckSUM_Result.csv"
$rHPath = "$oPath\CheckSUM_Result.html"
$tLogPath = "$oPath\File_CheckSUM_Transcript_Log.log"
$isMatch = "false"
$isFile = "false"
$IsRecurse = ""
$hashCheck = ""
$recurValue = ""
Start-Transcript -path $tLogPath -NoClobber -Append -Force
if(Test-Path $rPath){Remove-item $rPath}
if(Test-Path $rHPath){Remove-item $rHPath}
# Defining CSS Style for HTML Report
$Header = @"
<style>
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
P {color:Green;font-weight:bold}
H4{color:Blue;font-weight:bold}
</style>
"@
"First Path,First Hash,Second Path,Second Hash, Compare Result" | Out-File $rPath -Append -Encoding ASCII
# Input First File or Folder
do{
$firstPath = Read-Host -Prompt 'Enter First File or Folder'
if(!(Test-Path $firstPath)){write-host "Invalid Path $firstPath.Provide correct Path" -foregroundcolor red;$firstPath = ""}
}while(([String]::IsNullOrEmpty($firstPath)))
# Input Second File or Folder
do{
$secondPath = Read-Host -Prompt 'Enter Second File or Folder'
if(!(Test-Path $secondPath)){write-host "Invalid Path $secondPath.Provide correct Path" -foregroundcolor red;$secondPath = ""}
}while(([String]::IsNullOrEmpty($secondPath)))
# Input Scan type choice
do{
$IsRecurse = Read-Host -Prompt "Enter 'R' for Recurse or any other key for No-Recurse"
}while(([String]::IsNullOrEmpty($IsRecurse)))
write-host "You have entered First Path : $firstPath `nYou have entered First Path : $secondPath" -foregroundcolor green
# Check if entered data are as per the standard requirement of scan
if(((Get-Item $firstPath) -is [System.IO.DirectoryInfo]) -and ((Get-Item $secondPath) -is [System.IO.DirectoryInfo])){
write-host "You have entered Directory Path, All files and folders inside the Directory will be scanned and compared" -foregroundcolor green
$isMatch = "true"
$isFile = "false"
}
elseif(((Get-Item $firstPath) -is [System.IO.FileInfo]) -and ((Get-Item $secondPath) -is [System.IO.FileInfo])){
write-host "You have entered a File Path,Only entered File will be scanned and compared" -foregroundcolor green
$isMatch = "true"
$isFile = "true"
}
else{write-host "Cannot compare if Object type does not match!Please provide correct information!" -foregroundcolor red;Exit}
# Start scanning here
if($isMatch){
# Scan one file when enter file scans
if($isFile -eq "true"){
$fHash = $sHash = $hashCheck = ""
write-host "scanning First File : $firstPath" -foregroundcolor green
$fScan = Get-FileHash $firstPath -Algorithm MD5
write-host "scanning Second File : $secondPath" -foregroundcolor green
$sScan = Get-FileHash $secondPath -Algorithm MD5
$fHash = $fScan.Hash
$sHash = $sScan.Hash
if($fHash -eq $sHash){$hashCheck = "MATCHED"}else{$hashCheck = "NOT MATCHED"}
write-host "displaying Formatted result" -foregroundcolor green
"$firstPath,$fHash,$secondPath,$sHash,$hashCheck" | Out-File $rPath -Append -Encoding ASCII
# Printing HTML output on-screen
get-content $rPath | ConvertFrom-CSV | ConvertTo-Html -Title "MD5 CheckSUM Comparison Report" -Head $Header -body "<P>First Path : $firstPath</P><P>Second Path : $secondPath</P> " -pre "<P>MD5 CheckSUM Comparison Report</P>" > $rHPath
start $rHPath
}
else{
# Scans Directories and Subdirectories here
if($IsRecurse.ToUpper() -eq "R"){$recurValue = "Recursive Scan";$allScan = Get-ChildItem -Path $firstPath -recurse}
else{$recurValue = "Non-Recursive Scan";$allScan = Get-ChildItem -Path $firstPath}
$allScan | ForEach-Object {
# Generate file name in destination folder
$DstFileName = $FirstFile = $FirstFileHash = $SecondFile = $SecondFileHash = $hashCheck = ""
$DstFileName = Resolve-Path -Path (Join-Path $secodPath $_.FullName.Substring(($firstPath.Length)+1))
#$DstFileName = Resolve-Path -Path (Join-Path -Path $secondPath -ChildPath (Split-Path -Path $_.FullName -Leaf))
$FirstFile = $_.FullName
if(!$_.PsIsContainer){
$FirstFileHash = (Get-FileHash -Path $_.FullName -Algorithm MD5).Hash
$SecondFile = $DstFileName
$SecondFileHash = (Get-FileHash -Path $DstFileName -Algorithm MD5).Hash
if($FirstFileHash -eq $SecondFileHash){$hashCheck = "MATCHED"}
else{$hashCheck = "NOT MATCHED"}
"$FirstFile,$FirstFileHash,$SecondFile,$SecondFileHash,$hashCheck" | Out-File $rPath -Append -Encoding ASCII
}
}
# Printing HTML output on-screen
get-content $rPath | ConvertFrom-CSV | ConvertTo-Html -Title "MD5 CheckSUM Comparison Report" -Head $Header -body "<P>First Path : $firstPath</P><P>Second Path : $secondPath</P> <P>Scan Type : $recurValue</P>" -pre "<P>MD5 CheckSUM Comparison Report</P>" > $rHPath
start $rHPath
}
}
Screenshots of the script run process and output :