我知道PowerShell管道通过获取一个cmdlet的输出并将其作为输入传递给另一个cmdlet来工作。但是如何做呢?
第一个cmdlet是否完成,然后一次传递所有输出变量,然后由下一个cmdlet处理?
或者,第一个cmdlet的每个输出一次取一个,然后通过所有剩余的管道cmdlet运行?
答案 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。