简体   繁体   English

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

[英]Does PowerShell automatically convert pipeline objects to strings as needed?

The help for Split-Path states that the parameters -LiteralPath and -Leaf are incompatible: Split-Path的帮助说明参数-LiteralPath-Leaf不兼容:

SYNTAX

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

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

This command failing confirms it:此命令失败确认:

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

And yet, piping works just fine:然而,管道工作得很好:

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

Why is that?这是为什么?

I thought Split-Path would receive an object from the pipeline and try to bind that object's PSPath property to its -LiteralPath parameter (alias: PSPath ), as explained here .我认为Split-Path会从管道接收 object 并尝试将该对象的PSPath属性绑定到它的-LiteralPath参数(别名: PSPath ),如此所述。

I imagine that because I supplied the -Leaf switch, the parameter binder knew to use the parameter set containing -Leaf , which took -LiteralPath out of the picture.我想因为我提供了-Leaf开关,所以参数绑定器知道使用包含-Leaf的参数集,这将-LiteralPath排除在外。 But then how does PSPath end up bound to -Path ?但是PSPath最终如何绑定到-Path呢? Does the binder automatically call .ToString() on the object to obtain the path as a string, which it can then bind to -Path by value instead of by property name ?活页夹是否自动调用 object 上的.ToString()以获取字符串形式的路径,然后它可以按值而不是按属性名称绑定到-Path How does it know to do that?它怎么知道要那样做?

I tried using Trace-Command, but I'm unable to understand the output.我尝试使用 Trace-Command,但无法理解 output。

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

Following the output of Trace-Command when using -Leaf (trimmed down here):在使用 -Leaf 时遵循Trace-Command-Leaf (此处已删减):

# 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

Based on the trace output, powershell tries using named args > pipeline, no coercion > pipeline, with coercion in order .基于跟踪 output,powershell 尝试使用named args > pipeline, no coercion > pipeline, with coercion按顺序进行强制。 It tries each with every possible parameter set in the order they're defined in. You can list the parameter sets in order with (Get-Command Split-Path).Definition .它会按照它们定义的顺序尝试每个可能的参数集。您可以使用(Get-Command Split-Path).Definition按顺序列出参数集。

  • Without -Leaf , it's able to use the -LiteralPath parameter set with no coercion first, so that's what runs.没有-Leaf ,它可以首先使用没有强制转换的-LiteralPath参数集,所以这就是运行。

  • With -Leaf , it excludes the -LiteralPath parameter set, and is finally able to use -Path by coercing the pipeline object to string.使用-Leaf ,它排除了-LiteralPath参数集,并且最终能够通过将管道 object 强制为字符串来使用-Path

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM