我对 Bash 比对 Powershell 更熟悉,有时我对后者的对象模型感到困惑。
看着documentation of Get-FileHash ,似乎有3种指定输入的方法:
前两个取文件名,第三个取数据流。
现在,
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
所期望的输入类型?
最佳答案
System.IO.FileInfo
/System.IO.DirectoryInfo
PowerShell cmdlet 输出的实例具有 .PSPath
房产 [*] 包含实例的完全限定路径,它是以 PS 提供程序名称为前缀的完整文件系统路径(例如,Microsoft.PowerShell.Core\FileSystem::C:\windows
)。
文件处理 cmdlet 如Get-FileHash
有一个 -LiteralPath
参数 别名为 -PSPath
.
因为一个 -LiteralPath
参数(通常)通过属性名称接受来自管道的输入,输入对象具有 .PSPath
属性自动绑定(bind)到它 ,凭借 PSPath
参数别名。
作为旁白:
-Path
参数,将其参数解释为 wildcard expressions ,而不是文字路径。-Path
,这尤其意味着它们确实被解释为通配符 - 虽然这通常无关紧要,因为大多数文字路径不包含通配符元字符,但包含 [
的路径确实如此。和 ]
,然后被误解;避免这种误解需要将它们转义为 `[
和 `]
,如this answer所示. Get-FileHash
,具体来说,不通过管道接受字符串 - 请参阅 this answer详情。如何发现 这种行为:
Get-Help Get-FileHash -Parameter LiteralPath | Select-Object name, aliases, pipelineinput
在这种情况下也可以使用,但这种方法通常仅限于 MAML 附带的目标命令基于 -based 的帮助文件,甚至那些提供的帮助文件也可能与实际命令定义不同步。 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
[*] 添加此属性等的是 PowerShell 的文件系统提供程序。所有 PowerShell providers以这种方式装饰它们的输出项,例如
Microsoft.Win32.RegistryKey
注册表提供程序输出的实例。底层 .NET 类型没有它。见 this answer了解更多信息。
关于powershell - 为什么 "Get-ChildItem -File | Get-FileHash"有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60176733/