Note: This answer addresses your question as originally asked. For the solution to your actual question, see this answer.
Don't use -Filter *.* if your true intent is to match files only - files can lack an extension (e.g. file) and, conversely, directories may have one (e.g. dir.foo)
Don't use Resolve-Path -RelativePath if your intent is to pipe file-information objects to Get-FileHash.
- Instead, pipe the
System.IO.FileInfo instances output by Get-ChildItem directly to Get-FileHash.
Therefore, use the following:
Get-ChildItem -Path .\subdir\ -Recurse -File | Get-FileHash
Your intermediate Resolve-Path -Relative call does work in PowerShell (Core) 7+ - but not in Windows PowerShell - but either way there is no benefit to using it, because the .Path property of the objects output by Get-FileHash always contain the full path, irrespective of whether the input path was relative or not.
Again, see this answer for how to get relative paths in the desired output objects.
To put it differently:
Piping a - relative or absolute - path as a string to Get-FileHash should work, but - due to a limitation in Windows PowerShell - doesn't (fixed in PowerShell (Core) 7+).
In general, the following should apply to all file-processing cmdlets, which have both a -Path and a -LiteralPath parameter (the former potentially accepting wildcard expressions, the latter accepting literal (verbatim) paths only):
They accept string input via the pipeline, which binds to the -Path parameter (via that parameter's ValueFromPipeline property)
- Notably, this means that path strings are interpreted as wildcard expressions, not as literal paths.
They accept System.IO.FileInfo / System.IO.DirectoryInfo input via the pipeline - as output by Get-Item and Get-ChildItem, for instance - which binds to the -LiteralPath parameter (via that parameter's ValueFromPipelineByPropertyName property, which binds to the input objects' .PSPath property, by virtue of -PSPath being a declared alias for -LiteralPath)
As an aside: Perhaps surprisingly, the pipeline-binding rules are not also applied to passing a
-LiteralPath value as a direct argument rather than via the pipeline - see GitHub issue #6057
To inspect the pipeline-relevant properties of the -Path and -LiteralPath parameters of a given cmdlet:
If you don't also need to see the alias names of these parameters,[1] only the pipeline-binding behavior with respect to their primary names, the solution is simple:
& { Get-Help $args[0] -Parameter *Path } Get-FileHash
If you do want to see the parameter alias names, it gets a bit more complicated, unfortunately (note how Get-FileHash is passed as an argument to the script block ({ ... } being invoked; you may pass any cmdlet name of interest):
& {
(Get-Command $args[0]).ParameterSets.Parameters | Where-Object { $_.Name -like '*Path' } |
Select-Object Name, Aliases, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterType
} Get-FileHash | Format-Table
Windows PowerShell output:
Name Aliases ValueFromPipeline ValueFromPipelineByPropertyName ParameterType
---- ------- ----------------- ------------------------------- -------------
Path {} False False System.String[]
LiteralPath {PSPath} False True System.String[]
PowerShell (Core) 7+ output:
Name Aliases ValueFromPipeline ValueFromPipelineByPropertyName ParameterType
---- ------- ----------------- ------------------------------- -------------
Path {} True True System.String[]
LiteralPath {PSPath, LP} False True System.String[]
The above shows that Get-FileHash:
In Windows PowerShell:
- accepts no direct string input via the pipeline (no
ValueFromPipeline property value set to $true).
- only binds objects that have a
.PSPath property to -LiteralPath (i.e., objects output by Get-Item and Get-ChildItem), due to ValueFromPipelineByPropertyName being $true, by that property's value.
In PowerShell Core 7+:
- does accept direct string input, via the
-Path parameter, and also via input objects that have a .Path property.
- as in Windows PowerShell, binds objects that have a
.PSPath property to -LiteralPath by that property's value, and, additionally, analogously objects with a .LP property, which is implied by the fact that in PowerShell (Core) -LP is now an official alias of -LiteralPath.
[1] It is unfortunate that Get-Help -Parameter output doesn't list aliases - see GitHub issue #13418. A related problem is that you cannot request parameter information via an alias - see GitHub issue #6183.