powershellforeachexpandoobject

In Powershell how do "ExpandProperty" of multiple values?


Seems like this should be simple enough.

get-childitem -path "E:\Test 1" -Recurse -File | foreach-Object { $fsize=(get-Item $_.FullName).Length ; $hash=(get-FileHash $_.Fullname -Algorithm MD5 | Select-Object Hash,Path ); write-host $fsize $hash }

This will result in an output like this:

18 @{Hash=2FC4C77B6792F3DA856E77486F849105; Path=E:\Test 1\file 1.txt}

Now I just want to display file size, file hash, file path.

I know I can use -ExpandProperty for a single property but how do I expand for both hash and path?

This works fine for just the Hash:

get-childitem -path "E:\Test 1" -Recurse -File | foreach-Object { $fsize=(get-Item $_.FullName).Length ; $hash=(get-FileHash $_.Fullname -Algorithm MD5 | Select-Object Hash,Path -ExpandProperty Hash); write-host $fsize $hash }

which results in:

18 2FC4C77B6792F3DA856E77486F849105

But you can't use -ExpandProperty with multiple values

get-childitem -path "E:\Test 1" -Recurse -File | foreach-Object { $fsize=(get-Item $_.FullName).Length ; $hash=(get-FileHash $_.Fullname -Algorithm MD5 | Select-Object Hash,Path -ExpandProperty Hash,Path); write-host $fsize $hash }

How can I extract the Path as well so it displays like this?

18 2FC4C77B6792F3DA856E77486F849105 E:\Test 1\file 1.txt

Thanks in advance for your patience with me and assistance.


Solution

  • You don't need to call Get-Item to retrieve the file's Length - you already have the exact same information from Get-ChildItem.

    In order to get multiple property values from Get-FileHash attached to each file without having to call Get-FileHash multiple times for each, you can use Select-Object twice in a row to first extract the output from Get-FileHash, and then use -ExpandProperty against that:

    $files = Get-ChildItem -Path "E:\Test 1" -Recurse -File
    $lengthAndHashObject = $files |Select Length,@{Name='FileHashOutput';Expression={$_ |Get-FileHash |Select-Object Hash,Path}} 
    $finalObjects = $lengthAndHashObject |Select Length -ExpandProperty FileHashOutput
    
    # or as a single pipeline:
    Get-ChildItem -Path "E:\Test 1" -Recurse -File |Select Length,@{Name='FileHashOutput';Expression={$_ |Get-FileHash |Select-Object Hash,Path}} |Select Length -ExpandProperty FileHashOutput
    

    The Path value you get from Get-FileHash isn't really necessary either - you already have the same information from the FullName property on the file info object and can do just a single pass with Select-Object:

    Get-ChildItem -Path "E:\Test 1" -Recurse -File |Select Length,@{Name='Path';Expression='FullName'},@{Name='Hash';Expression={$_ |Get-FileHash |ForEach-Object Hash}}