Creating a file of md5 hashes for all files in a directory in PowerShell 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)
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.