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

8

我比较熟悉Bash,有时候会被Powershell的对象模型搞混。

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

  • 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

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


1
也许检索默认属性名称有答案... - Filburt
1
@Filburt:该帖子讨论的是(显示)_格式化,而这个问题是关于_参数绑定的。 - mklement0
1
请参阅李·霍姆斯(MS PowerShell 开发团队)的博客文章,了解有关 类型转换魔法 的更多信息。 - ives
3个回答

10
由PowerShell cmdlet输出的System.IO.FileInfo / System.IO.DirectoryInfo实例具有包含实例完全限定路径的.PSPath属性[*],即完整的文件系统路径,前缀为PS提供程序名称(例如:Microsoft.PowerShell.Core\FileSystem::C:\windows)。
Get-FileHash这样的文件处理 cmdlet具有一个-LiteralPath参数它的别名为-PSPath
因为一个-LiteralPath参数(通常)通过属性名称从管道接受输入,具有.PSPath属性的输入对象自动绑定到它,由于PSPath参数别名。
顺便说一下:
  • 文件处理 cmdlet 还具有一个-Path参数,它将其参数解释为wildcard表达式,而不是字面路径。

    • 当您将路径字符串传递给此类 cmdlet 时,它们会绑定到-Path,这意味着它们确实被解释为通配符 - 尽管这通常并不重要,因为大多数字面路径不包含通配符元字符,但对于包含[]的路径则会被错误解释;避免此错误解释需要将它们转义为`[`],如this answer中所示。
  • 由于Windows PowerShell中的一个错误(在 PowerShell (Core) 7+ 中已修复),特别是Get-FileHash无法通过管道接受字符串 - 有关详细信息,请参见this answer


如何发现这种行为:

parameter description

  • 编程方式:

    • 注意:在这种情况下,Get-Help Get-FileHash -Parameter LiteralPath | Select-Object name, aliases, pipelineinput也可以工作,但是这种方法通常仅限于目标命令,其带有MAML-based的帮助文件,并且即使有这些文件的命令定义可能会与实际命令定义不同步
& {
  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

[*] PowerShell的文件系统提供程序添加了此属性,以及其他属性。所有PowerShell 提供程序 都会以这种方式装饰其输出项,例如由注册表提供程序输出的Microsoft.Win32.RegistryKey实例。底层的.NET类型没有这个属性。有关更多信息,请参见此答案


3

1
奇怪的是,路径不起作用。[pscustomobject]@{path='there'} | get-filehash - js2010
4
在PowerShell 5.1中,参数PathAccept pipeline input属性为False。请参阅(Get-Command Get-FileHash).Definition - JosefZ
1
@JosefZ - 感谢您的纠正![pscustomobject]@{LiteralPath='PATH'} | Get-FileHash - kuujinbo

0

看起来它使用了pspath属性。

dir there | select pspath | get-filehash

Algorithm  Hash                                                                Path
---------  ----                                                                ----
SHA256     44723DD4D0E0D46A3C7FA8ACA254B61C27B6B5789F96177E82C80700409F1535    C:\users\...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接