Powershell foreach-object循环似乎总是为每个对象运行进程块

时间:2014-08-11 19:15:48

标签: powershell

当我运行get-childitem charsets.pack时,我看到了:

PS C:\opt\jdk\jdk7u67\jre\lib> Get-ChildItem .\charsets.pack


    Directory: C:\opt\jdk\jdk7u67\jre\lib


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2014-07-25  10:24 AM    2172877 charsets.pack

因此,当我运行Get-ChildItem *.pack | ForEach-Object -Process {get-childitem $_.name}时,我希望看到每个文件都重复上一个输出。相反,我得到

PS C:\opt\jdk\jdk7u67\jre\lib> Get-ChildItem *.pack | ForEach-Object -Process {get-childitem $_.name}


    Directory: C:\opt\jdk\jdk7u67\jre\lib


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2014-07-25  10:24 AM    2172877 charsets.pack
-a---        2014-07-25  10:24 AM    1940370 deploy.pack
-a---        2014-07-25  10:24 AM     221856 javaws.pack
-a---        2014-07-25  10:24 AM    4163103 jfxrt.pack
-a---        2014-07-25  10:24 AM     176166 jsse.pack
-a---        2014-07-25  10:24 AM     532239 plugin.pack
-a---        2014-08-11  11:30 AM   18345177 rt.pack

是什么给出的?看起来它实际上没有为每个对象运行进程块,而是进行某种优化。但是当我运行Get-ChildItem *.pack | ForEach-Object -Process {Get-Date}时,我得到了我期望的结果:

PS C:\opt\jdk\jdk7u67\jre\lib> Get-ChildItem *.pack | ForEach-Object -Process {Get-Date}

Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30
Monday, 11 August, 2014 12:11:30

Fwiw,我更习惯于抨击,而且可能会带来这些期望。

2 个答案:

答案 0 :(得分:4)

我认为这里真正的问题是你误解了管道是如何工作的。你的ForEach正在输出管道末端的[FileInfo]对象,因为它没有指定输出,它将到达管道末端的所有内容输出到格式化程序,并将集合指定为[ FileInfo]对象并显示它们,如OP中所示。

如果要查看每个文件输出,则必须将Get-ChildItem传递给Out-String,或者将某些此类传递给 ForEach循环。虽然这真的只是做了双重工作,因为原始的Get-ChildItem将[FileInfo]对象传递给ForEach循环,并且执行Get-ChildItem $_.Name(你可能在那里意味着FullName)提供完全相同的[FileInfo]对象,因此可以缩短为$_ | Out-String

所以你真的没有在ForEach循环中输出到主机,你只是将一个FileInfo对象输入ForEach循环进行处理,然后查找该对象并将其提供给管道以便输出较晚,就像你的ForEach循环不存在一样。

我希望这有助于澄清事情。

答案 1 :(得分:1)

Get-ChildItem基本上相当于dirls(PowerShell实际上是对Get-ChildItem的别名)。

就像现在一样,你正试图让孩子获得个别文件(而且他们没有孩子)。另一种方法是调用Get-Item $_.Name,虽然这看起来有点傻,因为它的输出与$_首先引用的对象相同。

我可能误解了你想要的东西,但我认为你只需要在你的街区中使用$_