4
\$\begingroup\$

I have been trying to write the md5 hashes for all files in a directory and its subdirectories to a file. Ideally, replicating the output of the Unix command find . -type f -exec md5sum {} + (i.e. two columns: lowercase hashes and relative file paths [with forward slashes] separated by a space and terminated only by a line feed).

With a lot of help from Mark Wragg, LotPings and others on stackoverflow, the following command appears to compute md5 hashes for all files in a directory and its subdirectories (including those files without file extensions and those with square brackets in the filename).

(Get-FileHash -Algorithm MD5 -LiteralPath (Get-ChildItem -Recurse -File).fullname | ForEach-Object{"{0} {1}" -f $_.Hash.ToLower(),(Resolve-Path -LiteralPath $_.Path -Relative)} | Out-String) -replace '\r(?=\n)' -replace '\\','/' | Set-Content -NoNewline -Encoding ascii $ENV:USERPROFILE\Desktop\hashes.txt

The two uses of -LiteralPath seems to help with filenames containing square brackets and (Get-ChildItem -Recurse -File).fullname gets the full path of all nested files, including those without file extensions. The rest is just formatting.

Can any one tell me where I can find more information about .fullname? I've tried searching for it on Google but without any luck.

I had used Get-ChildItem "*.*" -Recurse, which gives full file paths but only for files with dots in the filename. Whereas, Get-ChildItem "*" -Recurse doesn't always give the full path for some reason (and returns both files and folders). Compare:

Get-ChildItem "*.*" -Recurse | foreach-object { "$_" }

Get-ChildItem "*" -Recurse | foreach-object { "$_" }

The order of entries in the hashes file won't be the same as those from the Unix command but compare-object in PowerShell appears to ignore the order of lines, e.g. (https://serverfault.com/questions/5598/how-do-i-diff-two-text-files-in-windows-powershell)

compare-object (get-content oldHashes.txt) (get-content newHashes.txt)

or

diff (cat oldHashes.txt) (cat newHashes.txt)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Why MD5 instead of SHA-256? \$\endgroup\$ Commented Aug 1, 2019 at 7:06

1 Answer 1

1
\$\begingroup\$

I rewrote your code from scratch how I would have written it myself. Maybe it can give you some ideas.

$lines = gci -Recurse -File | 
    Get-FileHash -Algorithm MD5 | % { 
        $unixPath = $_.Path -replace '\\','/'
        $hash = $_.Hash.ToLower()
        "$hash $unixPath" }

$lines -join "`n" | 
    Out-File -Encoding ascii -NoNewline $ENV:USERPROFILE\Desktop\hashes.txt

Notes:

  • gci is an alias for Get-ChildItem.
  • I used gci -File to get files only.
  • % is an alias for ForEach-Object.
  • I didn't use it, but here is the help for FileSystemInfo.FullName
  • cat is an alias for Get-Content.

Feel free to ask any questions.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.