Home > OS >  Compare folder to a hash file
Compare folder to a hash file

Time:09-22

There are a lot of questions and answers about comparing the hash of two folder for integrity like this one. Assuming I have a folder that I copied to a backup medium (External drive, flash, optical disc) and would like to delete the original to save space.

What is the best way to save the original's folder hashes (before deletion) in a text file perhaps and check the backup's integrity much later against that file.

CodePudding user response:

Note that if you delete the originals first and later find that the backup lacks integrity, so to speak, all you'll know is that something went wrong; the non-corrupted data will be gone.


You can create a CSV file with 2 columns, RelativePath (the full file path relative to the input directory) and Hash, and save it to a CSV file with Export-Csv:

$inputDir = 'C:\path\to\dir' # Note: specify a *full* path.
$prefixLen = $inputDir.Length   1

Get-ChildItem -File -Recurse -LiteralPath $inputDir |
  Get-FileHash |
    Select-Object @{ 
                    Name='RelativePath'
                    Expression={ $_.Path.Substring($prefixLen) } 
                  }, 
                  Hash |
    Export-Csv originalHashes.csv -NoTypeInformation -Encoding utf8

Note: In PowerShell (Core) 7 , neither -NoTypeInformation nor -Encoding utf8 are needed, though note that the file will have no UTF-8 BOM; use -Encoding utf8bom if you want one; conversely, in Windows PowerShell you invariably get a BOM.

Note:

  • The Microsoft.PowerShell.Commands.FileHashInfo instances output by Get-FileHash also have an .Algorithm property naming the hashing algorithm that was used ('SHA256' by default, or as specified via the -Algorithm parameter).
    If you want this property included (whose value will be the same for all CSV rows), you simply add Algorithm to the array of properties passed to Select-Object above.

  • Note how a hashtable (@{ ... }) passed as the second property argument to Select-Object serves as a calculated property that derives the relative path from each .Path property value (which contains the full path).

You can later apply the same command to the backup directory tree, saving to, say, backupHashes.csv, and compare the two CSV files with Compare-Object:

Compare-Object (Import-Csv -LiteralPath originalHashes.csv) `
               (Import-Csv -LiteralPath backupHashes.csv) `
               -Property RelativePath, Hash

Note: There's no strict need to involve files in the operation - one or both output collections can be captured in memory and can be used directly in the comparison - just omit the Export-Csv call in the command above and save to a variable ($originalHashes = Get-ChildItem ...)

  • Related