Why does "Get-ChildItem -File | Get-FileHash" work?
System.IO.FileInfo
/ System.IO.DirectoryInfo
instances output by PowerShell cmdlets have a .PSPath
property[*] that contains the instances' fully qualified path, which is the full file-system path prefixed by the PS provider name (e.g., Microsoft.PowerShell.Core\FileSystem::C:\windows
).
File-processing cmdlets such as Get-FileHash
have a -LiteralPath
parameter which has an alias name of -PSPath
.
Because a -LiteralPath
parameter (typically) accepts input from the pipeline by property name, input objects that have a .PSPath
property automatically bind to it, by virtue of the PSPath
parameter alias name.
How to discover this behavior:
- Via the online help topic:
Programmatically:
- Note:
Get-Help Get-FileHash -Parameter LiteralPath | Select-Object name, aliases, pipelineinput
works too in this case, but this approach is generally restricted to target commands that come with MAML-based help files, and even those that do can have help files that are out of sync with the actual command definition.
- Note:
PS> & {
Get-Command $args[0] | % Parameters | % $args[1] |
Select-Object Name, Aliases, @{
n = 'Accepts pipeline input';
e = { $(if ($_.Attributes.ValueFromPipeline) { 'by value' }), $(if ($_.Attributes.ValueFromPipelineByPropertyName) { 'by property name' }) -join ', ' -replace '^, ' }
}
} Get-FileHash LiteralPath
Name Aliases Accepts pipeline input
---- ------- ----------------------
LiteralPath {PSPath, LP} by property name
[*] It is PowerShell's file-system provider that adds this property, among others. The underlying .NET types do not have it. See this answer for more information.
From the About Functions Advanced Parameters documentation, ValueFromPipelineByPropertyName argument section:
The ValueFromPipelineByPropertyName argument indicates that the parameter accepts input from a property of a pipeline object. The object property must have the same name or alias as the parameter.
For example, if the function has a ComputerName parameter, and the piped object has a ComputerName property, the value of the ComputerName property is assigned to the function's ComputerName parameter.
Update: Originally linked the wrong source code file. The correct Get-FileHash
source code is here. As @mklement0 correctly answered the Get-ChildItem
cmdlet outputs an object with a PSPath
property, which makes this work.