【问题标题】:PowerShell ForEach-Object and Pipelining - upstreamPowerShell ForEach-Object 和流水线 - 上游
【发布时间】:2021-07-26 13:16:28
【问题描述】:

我有一个小的 powershell 脚本,它可以将所有文件和文件夹分别压缩到一个文件夹中:

dir | ForEach-Object { 7z a -tzip -mmt=32 $_.BaseName $_.Name };

假设我的目录中有两个文件夹:

test1
test2

没有别的。目前,此代码将创建“test1.zip”和“test2.zip”,其中包含各自的文件夹,但也再次包含它们自己(即 test1.zip)。对于两个文件夹,7z 被调用四次:每个文件夹一次创建一个 zip,然后每个新的 zip 文件一次通过包含 zip 本身来更新 zip。显然这不是我们想要的结果:

Content of test1.zip:

test1 
test1.zip

管道似乎获取了新文件的更新并将它们转发到 ForEach-Object 命令,这意味着“test1.zip”会立即添加到“test1.zip”中。

我对为什么会发生这种情况感到困惑(更令人不安的是:并非所有运行都如此),因为我认为该语句是从左到右完成的,这意味着 dir 并且它的输出已完成并且已修复,然后(可能并行)由ForEach-Object 处理。

我哪里错了?

dir | ForEach-Object { Write-Host ("I see:"+$_.Name);7z a -tzip $_.Name $_.Name };

表明即使是新创建的 zip 文件也通过管道传输到 ForEach-Object。

【问题讨论】:

  • 所以你是说,当命令执行时,它会显示: test1.zip > test1 > ... ?这不就是它的目的吗?所以可以用相同的文件夹名解压。
  • 不,test1.zip的内容是:test1(文件夹)和test1.zip,其中在运行此 powershell 行之前不存在。对于两个文件夹,7z 被调用四次:为每个文件夹创建一个 zip,然后为每个新 zip 调用一次,通过将 zip 包含在自身中来更新 zip。我在原始帖子中添加了这一点。
  • 不,每次在每个管道元素中处理一个对象。您必须在 (dir) 周围加上括号以确保它首先完成。
  • @js2010 非常感谢。我对powershell很陌生,感谢您的评论,我现在了解了管道流程。 dir 命令基本上暂停,直到管道完成第一个对象。这个评论也帮助了我。 stackoverflow.com/questions/54354270/…
  • 这是重命名文件的常见问题。

标签: powershell directory 7zip foreach-object


【解决方案1】:

通常让 dir 先完成,在它周围加上括号,否则管道将一次来回移动一个对象,并可能包含新文件。重命名脚本会发生这种情况。我认为在 powershell 7 中这种情况不太常见。

(dir) | ForEach-Object { 7z a -tzip -mmt=32 $_.BaseName $_.Name }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 2011-12-06
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多