PowerShell 是否会根据需要自动将管道对象转换为字符串?

Does PowerShell automatically convert pipeline objects to strings as needed?

Split-Path 的帮助指出参数 -LiteralPath-Leaf 不兼容:

SYNTAX

    Split-Path [-Path] <System.String[]> -Leaf [-Resolve]  # ...

    Split-Path -LiteralPath <System.String[]> [-Resolve]  # ...

此命令失败确认:

Split-Path -LiteralPath 'C:\foo.txt' -Leaf
# Split-Path: Parameter set cannot be resolved using the specified named parameters.
# One or more parameters issued cannot be used together

然而,管道工作得很好:

Get-Item 'C:\foo.txt' | Split-Path -Leaf

这是为什么?

我认为 Split-Path 会从管道接收一个对象并尝试将该对象的 PSPath 属性 绑定到它的 -LiteralPath 参数(别名:PSPath),正如所解释的 .

我想因为我提供了 -Leaf 开关,参数绑定器知道使用包含 -Leaf 的参数集,这使 -LiteralPath 不在画面中。但是 PSPath 最终如何绑定到 -Path?活页夹是否自动在对象上调用 .ToString() 以获取字符串形式的路径,然后它可以通过值 而不是 [=43= 绑定到 -Path ]经过 属性名字?它怎么知道要这样做?

我尝试使用 Trace-Command,但无法理解输出。

Trace-Command ParameterBinding { Get-Item 'C:\foo.txt' | Split-Path -Leaf } -PSHost

在使用 -Leaf 时遵循 Trace-Command 的输出(此处删减):

# First, powershell binds any manually specified args (-Leaf):
BIND NAMED cmd line args [Split-Path]
  BIND arg [True] to param [Leaf] SUCCESSFUL

# Then it checks for required positional args
BIND POSITIONAL cmd line args [Split-Path]
BIND cmd line args to DYNAMIC parameters.
MANDATORY PARAMETER CHECK on cmdlet [Split-Path]

# Because -Leaf was specified, it knows only -Path is required, and tries to bind the object first:
BIND PIPELINE object to parameters: [Split-Path]
    PIPELINE object TYPE = [System.IO.FileInfo]
    BIND arg [C:\foo] to parameter [Path]
        BIND arg [C:\foo] to param [Path] SKIPPED  ## fails

# It tries again later on by coercing to string and succeeds:
    Parameter [Path] PIPELINE INPUT ValueFromPipeline WITH COERCION
    BIND arg [C:\foo] to parameter [Path]
        COERCE arg to [System.String[]]
        BIND arg [System.String[]] to param [Path] SUCCESSFUL

根据跟踪输出,powershell 尝试按 named args > pipeline, no coercion > pipeline, with coercion 的顺序使用。它会按照它们定义的顺序尝试每个可能的参数集。您可以按 (Get-Command Split-Path).Definition.

的顺序列出参数集
  • 没有 -Leaf,它可以先使用没有强制转换的-LiteralPath参数集,所以这就是运行。

  • -Leaf,排除了-LiteralPath参数集,终于可以用-Path了将管道对象强制转换为字符串。