1

I'm trying to create a text file with file names and their MD5 hash next to them. Doesn't really make sense, but it's for learning purposes.

This is how I calculate the hash:

$hash = Get-FileHash -Algorithm MD5 -Path $file | Select-Object Hash

Then I Out-File everything into a text file:

$file.Name + "`t`t" + $hash | Out-File -Append -FilePath ($destination + "inventory$i.txt")

Now every $hash value will look something like this:

@{Hash=2A396C91CB1DE5D7C7843970954CC1D4}

How can I get the "raw" Hash value from that string? Or is it even a string?

In my text file, I want it to look like this:

Name                    MD5 Hash
helloworld.txt          2A396C91CB1DE5D7C7843970954CC1D4

(By chance, does someone have a better idea for formatting this instead of using `t for tabulators?)

  • Your bonus question is a bit vague... What makes tabs "stupid"? What would make you consider something different "better"? :) – Mathias R. Jessen Mar 29 '22 at 12:32
  • I know... Weird question. I guess I want two seperate columns but that's not gonna be possible with a simple .txt right? Maybe it's possible to always jump to the same tab instead of always adding two like I did? –  Mar 29 '22 at 12:43
  • `Select-Object -ExpandProperty Hash` could work as well – Abraham Zinala Mar 29 '22 at 12:44
  • @sutterseba I would personally store the raw output from `Get-FileHash` in a CSV: `Get-FileHash -Path $file -Algorithm MD5 |Export-Csv ...`, then do the formatting whereever the data needs to be presented (eg. `Import-Csv ... |Select @{Name='Name';Expression={Split-Path $_.Path -Leaf}},Hash` or similar) – Mathias R. Jessen Mar 29 '22 at 12:46

1 Answers1

2

Select-Object Hash creates a new object with a single property Hash copied from the input object(s).

To get just the raw value of the Hash property from each input objcet, use ForEach-Object instead:

$hash = Get-FileHash -Algorithm MD5 -Path $file | ForEach-Object -MemberName Hash

That being said, instead of grabbing just the hash string from the result, you might want to use the result itself to create the output you need - this way you can easily adapt your script to hash multiple files in the future:

[CmdletBinding(DefaultParameterSetName = 'ByPath')]
param(
  [Parameter(Mandatory = $true, ParameterSetName = 'ByPath')]
  [string[]]$Path,

  [Parameter(Mandatory = $true, ParameterSetName = 'ByPSPath', ValueFromPipelineByPropertyName = $true)]
  [Alias('PSPath')]
  [string[]]$LiteralPath
)

process {
  Get-FileHash @PSBoundParameters |ForEach-Object {
    $fileName = Get-ItemPropertyValue -LiteralPath $_.Path -Name Name
    
    "${fileName}`t`t$($_.Hash)"
  }
}

Now you can do:

Get-ChildItem -Filter *.ext |.\yourScript.ps1 |Out-File -Append -Path path\to\output.txt
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206