PowerShell管道概念如何工作?

时间:2013-06-26 15:33:30

标签: powershell pipeline conceptual

我知道PowerShell管道通过获取一个cmdlet的输出并将其作为输入传递给另一个cmdlet来工作。但是如何做呢?

第一个cmdlet是否完成,然后一次传递所有输出变量,然后由下一个cmdlet处理?

或者,第一个cmdlet的每个输出一次取一个,然后通过所有剩余的管道cmdlet运行?

3 个答案:

答案 0 :(得分:11)

您可以通过简单的脚本来了解管道订单的工作原理:

function a {begin {Write-Host 'begin a'} process {Write-Host "process a: $_"; $_} end {Write-Host 'end a'}}
function b {begin {Write-Host 'begin b'} process {Write-Host "process b: $_"; $_} end {Write-Host 'end b'}}
function c { Write-Host 'c' }

1..3 | a | b | c

输出:

begin a
begin b
process a: 1
process b: 1
process a: 2
process b: 2
process a: 3
process b: 3
end a
end b
c

答案 1 :(得分:6)

Powershell管道以异步方式工作。这意味着第一个cmdlet的输出立即可用于第二个cmdlet一个对象(即使第一个cmdlet尚未完成执行)。

例如,如果您运行以下行:

dir -recurse| out-file C:\a.txt

然后按Control + C停止执行,您将看到目录的一部分被写入文本文件。

更好的例子是以下代码:(这对于删除驱动器c上的所有.tmp文件确实很有用)。

get-childitem c:\ -include *.tmp -recurse | foreach ($_) {remove-item $_.fullname}

每次第二个cmdlet中的$ _获取(单个文件)的值

答案 2 :(得分:1)

这两个答案都可以为您提供有关流水线的一些很好的信息。但是,还有更多要说的。

首先,为了直接解决您的问题,您提出了两种可能的管道工作方式。它们都是正确的...取决于管道两侧的cmdlet! 但是,管道应该工作的方式更接近您的第二个概念:一次处理一个对象。 (虽然在下一个对象启动之前,并不能保证对象会完全通过,因为管道中的每个组件都是异步的,正如S Nash所提到的那样。)

那么我的意思是"它取决于你的cmdlet" ? 如果您正在讨论Microsoft提供的cmdlet,它们可能都会按预期工作,尽可能高效地传递每个对象通过管道。但是,如果您正在谈论您编写的cmdlet,那么这取决于您编写它们的方式:编写成功管道的cmdlet就像编写成功的那些一样容易!

有两种主要的失败模式:

  • 在将任何输出发送到管道之前生成所有输出,或
  • 在处理之前收集所有管道输入。

当然,您想要争取的是在收到每个输入后立即对其进行处理,并在确定后立即发出输出。有关所有这些内容的详细示例,请参阅我发表在Simple-Talk.com上的文章Ins and Outs of the PowerShell Pipeline

相关问题