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.