为什么“Get-ChildItem -File | Get-FileHash”有效?

dan*_*iaz 7 powershell

我对 Bash 比对 Powershell 更熟悉,有时我对后者的对象模型感到困惑。

查看Get-FileHash文档,似乎有 3 种指定输入的方法:

  • Get-FileHash [-Path]
  • Get-FileHash [-LiteralPath]
  • Get-FileHash [-InputStream]

前两个取文件名,第三个取数据流。

现在,Get-ChildItem -File似乎输出System.IO.FileInfo对象,从什么Get-Member说:

$ Get-ChildItem -File | Get-Member
TypeName: System.IO.FileInfo
Run Code Online (Sandbox Code Playgroud)

然而管道Get-ChildItem -File | Get-FileHash工作正常。我的问题是,允许转换System.IO.FileInfo为预期的输入类型的机制是什么Get-FileHash

mkl*_*nt0 8

System.IO.FileInfo/ System.IO.DirectoryInfoPowerShell cmdlet 输出的实例具有一个.PSPath属性[*] ,其中包含实例的完全限定路径,即以 PS 提供程序名称(例如,Microsoft.PowerShell.Core\FileSystem::C:\windows)为前缀的完整文件系统路径。

文件处理的cmdlet,例如Get-FileHash有一个-LiteralPath参数,它有一个别名-PSPath

因为-LiteralPath参数(通常)通过属性名称接受来自管道输入,所以具有.PSPath属性的输入对象会根据PSPath参数别名自动绑定到它


如何发现这种行为:

参数说明

  • 以编程方式:

    • 注意:Get-Help Get-FileHash -Parameter LiteralPath | Select-Object name, aliases, pipelineinput这种情况下也适用,但这种方法通常仅限于基于MAML的帮助文件附带的目标命令,甚至那些有帮助文件的帮助文件与实际命令定义不同步
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
Run Code Online (Sandbox Code Playgroud)

[*] PowerShell 的文件系统提供程序添加了此属性等。底层的 .NET 类型没有它。有关更多信息,请参阅此答案