Skip to content

Instantly share code, notes, and snippets.

@iOnline247
Last active November 24, 2020 08:15
Show Gist options
  • Save iOnline247/77e9f1986536342a26a0db5a6bd89c51 to your computer and use it in GitHub Desktop.
Save iOnline247/77e9f1986536342a26a0db5a6bd89c51 to your computer and use it in GitHub Desktop.
Compare checksum of files or directories.
function logMsg($text, $color = [System.ConsoleColor]::green) {
Write-Host $text -foregroundcolor $color
Write-Host "`r`n"
}
<#
function Remove-DirectoryPathInfo ($fileInfo) {
$fileInfo.Path = $fileInfo.Path -replace "$([Regex]::Escape($testFiles[0].Parent.Parent.FullName))\\", ""
$fileInfo.Path = $fileInfo.Path -replace "$([Regex]::Escape($initialFiles[0].Parent.Parent.FullName))\\", ""
# "$([Regex]::Escape($parentDirectoryPath))\\"
# "$([Regex]::Escape($parentDirectoryPath+'\'))"
return $fileInfo
}
#>
function Get-Checksum {
param(
[Parameter(ValueFromPipeline = $true)]
$files,
[string[]]$ChecksumLogsPath = $null,
[ValidateSet("MD5", "SHA1", "SHA256", "SHA384", "SHA512", "RIPEMD160", "MACTripleDES")]
[string]$Algorithm = ("MD5", "SHA1", "SHA256", "SHA384", "SHA512", "RIPEMD160", "MACTripleDES")
)
BEGIN {
function getFormattedFileHash ($filePath, $Algorithm) {
$parentDirectoryPath = $file.DirectoryName
return Get-FileHash -LiteralPath $file.FullName -Algorithm $Algorithm | Select Hash, @{Name = 'FileName'; Expression = {$_.Path -replace "$([Regex]::Escape($parentDirectoryPath))\\", ""}}
}
$time = get-date
$logFile = $($env:userprofile + "\checkSum-" + $time.ticks + ".log")
}
PROCESS {
$files = $files | Where-Object { !$_.PSIsContainer }
foreach ($file in $files) {
$fileDeets = getFormattedFileHash -file $file -Algorithm $Algorithm
($fileDeets | Out-String).Trim() >> $logFile
}
}
END {
logMsg $("The checksum logfile was created: " + $logFile)
# Invoke-Item $logFile
return $logFile
}
}
function Compare-Checksum ($checksumLogPaths) {
logMsg "Generating hashes for each log file and comparing to the newly generated log hash..."
# Leave the .Trim() otherwise .Equals comparison doesn't work properly.
$checksumHashes = [psobject]@();
foreach ($checksumLog in $checksumLogPaths) {
# Does checksum log exist?
$logExists = Test-Path $checksumLog
if (!$logExists) {
logMsg "This log file doesn't exist: $($checksumLog)" ([System.ConsoleColor]::red)
continue;
}
# Verify checksums
# Leave the .Trim() otherwise .Equals comparison doesn't work properly.
$checksumHash = (Get-FileHash -LiteralPath $checksumLog -Algorithm SHA512 | Select-Object Hash).Hash
$checksumHashes += $checksumHash
Write-Host "Hash for $($checksumLog):" -ForegroundColor Green
Write-Host "$checksumHash`r`n" -BackgroundColor Green
}
$isMatchingChecksums = @($checksumHashes | Select -Unique).Count -eq 1
if ($isMatchingChecksums) {
logMsg "These checksums match.`r`n$checksumLogPaths`r`n`r`n"
}
else {
logMsg "These files are different:`r`n$checksumLogPaths`r`n$checksumHashes" ([System.ConsoleColor]::red)
}
}
try {
$initialPath = Read-Host -Prompt 'Give directory path...'
$testPath = Read-Host -Prompt 'Give path to test against...'
# C:\Users\mbramer\Documents\!src\infrastructure\
$checksumLogPaths = @();
$initialFiles = Get-ChildItem -Path $initialPath -Recurse
$testFiles = Get-ChildItem -Path $testPath -Recurse
$checksumLogPaths += ($initialFiles | Get-Checksum -Algorithm SHA256)
$checksumLogPaths += ($testFiles | Get-Checksum -Algorithm SHA256)
Compare-Checksum -checksumLogPaths $checksumLogPaths
} catch [Exception] {
Write-Error $_
}
function Get-FileHashIndex
{
<#
.Synopsis
Get File Hash for PowerShell V3 and Higher
.DESCRIPTION
Bringed C# how we retrieve File Hash to PowerShell Script.
This works equivalent to Get-FileHash (v4) but twice as faster and supports -Recurse switch.
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm MACTripleDES -Recurse} # 684.4821
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm MD5 -Recurse} # 631.5687
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm RIPEMD160 -Recurse} # 693.6726
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm SHA1 -Recurse} # 641.9092
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm SHA256 -Recurse} # 695.2601
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm SHA384 -Recurse} # 677.8795
measure-Command {Get-FileHashIndex -Path d:\test\test -Algorithm SHA512 -Recurse} # 685.4792
measure-Command {ls d:\test\test -Recurse -File | Get-FileHashIndex -Algorithm MD5} # 878.1032
measure-Command {ls d:\test\test -Recurse -File | Get-FileHash -Algorithm MD5} # 1364.2046
measure-Command {ls d:\test\test -Recurse -File | Get-FileHash -Algorithm SHA256} # 1488.3237
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm MACTripleDES -Recurse
Algorythm Hash Path
--------- ---- ----
MACTripleDES 40C3FEAAA71C928B2FC3D248F4DA86211FBC1726 D:\test\test\README.md
MACTripleDES 5DCE5F942594C97A9929D18507FB043FC23B917B D:\test\test\hoge\Thumbs.db
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm MACTripleDES
Algorythm Hash Path
--------- ---- ----
MACTripleDES 40C3FEAAA71C928B2FC3D248F4DA86211FBC1726 D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm MD5
Algorythm Hash Path
--------- ---- ----
MD5 7C865A164CE6DFC4AE0E61EED9A49B8E D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm RIPEMD160
Algorythm Hash Path
--------- ---- ----
RIPEMD160 92DD18916AA074B0931E63D14541C44F07783CDF D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm SHA1
Algorythm Hash Path
--------- ---- ----
SHA1 73A0294775D3A91F1EC91EEF58AD28C48A5B515A D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm SHA256
Algorythm Hash Path
--------- ---- ----
SHA256 50DB8AFF8EFE10C9CBAAA2BE941E841AFF5ECC... D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm SHA384
Algorythm Hash Path
--------- ---- ----
SHA384 A8E66530035B84816C4C8BD2D4E17CC00D5848... D:\test\test\README.md
.EXAMPLE
PS > Get-FileHashIndex -Path d:\test\test -Algorithm SHA512
Algorythm Hash Path
--------- ---- ----
SHA512 13A29B1D0C28ED69B441481282B3983F729D51... D:\test\test\README.md
.OUTPUTS
[PSCustomObject]
Incluide Algorithm, Hash and Path Property
#>
[CmdletBinding()]
param
(
[parameter(Mandatory = 1, Position = 0, ValueFromPipeline = 1, ValueFromPipelineByPropertyName =1)]
[Alias("PSPath", "LiteralPath")]
[string[]]$Path,
[parameter(Mandatory = 0, Position = 1, ValueFromPipelineByPropertyName =1, ParameterSetName = "MD5")]
[ValidateSet("MACTripleDES", "MD5", "RIPEMD160", "SHA1", "SHA256", "SHA384", "SHA512")]
[string]$Algorithm = "SHA256",
[parameter(Mandatory = 0, Position = 2, ValueFromPipelineByPropertyName =1)]
[switch]$Recurse
)
process
{
foreach ($p in $Path){ $list.Add($p) }
}
end
{
foreach ($l in $list){ Get-ChildItem -Path $l -File -Recurse:$Recurse | GetHashInfo }
}
begin
{
$list = New-Object 'System.Collections.Generic.List[string]'
filter GetHashInfo
{
try
{
[System.IO.FileStream]$stream = [System.IO.File]::OpenRead($_.fullname)
$hash = GetHash -Stream $stream -Algorithm $Algorithm
}
finally
{
$stream.Dispose()
}
return [PSCustomObject]@{
Algorithm = $Algorithm
Hash = $hash
Path = $_.FullName
File = $_
}
}
function GetHash ([System.IO.FileStream]$Stream, [string]$Algorithm)
{
try
{
$crypto = [System.Security.Cryptography.HashAlgorithm]::Create($Algorithm)
[byte[]]$hash = $crypto.ComputeHash($Stream)
return [System.BitConverter]::ToString($hash).Replace("-", [string]::Empty)
}
finally
{
$crypto.Dispose()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment