【问题标题】:Bash script - Parallel unzip and waiting for endingBash 脚本 - 并行解压缩并等待结束
【发布时间】:2017-07-18 14:06:53
【问题描述】:

我需要解压缩一些档案,我想加快这个过程。 这是我的一段脚本:

for archive in $path; do

    STEM=$(basename "${archive}" .gz)
    gunzip -c $archive > $here/$STEM

done

for file in `ls "$here"`; do
     ... processing ...
done

有没有办法一次解压缩多个(所有)档案并等待完成?

换句话说,我需要这样的东西:

for archive in $path; do

    ... parallel unzip ...

done

WAIT

for file in `ls "$here"`; do
     ... processing ...
done

谢谢

【问题讨论】:

  • 你真的不想像那样解析ls 的输出;只需使用 glob:for file in "$here"/*;.
  • @TobySpeight for file in ls $pathfor file in $path 有什么区别?
  • 不多 - 如果任何文件名可能包含空格,它们都是不安全的。最好将path 设为 Bash 数组,并使用 for archive in "${path[@]}" 对其进行迭代。

标签: bash gzip gunzip


【解决方案1】:

您可以使用 GNU Parallel 非常简洁地做到这一点,如下所示:

parallel 'gunzip -c {} > "$here/$(basename {} .gz)"' ::: $path

请使用小目录中几个文件的副本进行测试,直到您掌握了窍门。

如果您有 10,000 个文件要解压缩,这不会突然启动 10,000 个 unzip 作业 - 相反,如果您说 8 个 CPU 内核,它将一次运行 8 个 unzip 进程,直到所有 10,000 个完成。您可以一次将作业数量更改为固定数量,或可用 CPU 的某个百分比。

您还可以通过parallel --progress ...parallel --bar ... 获得进度表。

您也可以使用parallel --dry-run ...GNU Parallel 告诉您它在不做任何事情的情况下会做什么。

【讨论】:

    【解决方案2】:

    只需在 gunzip 后加一个 & 号即可:

    for archive in $path; do
    
        STEM=$(basename "${archive}" .gz)
        gunzip -c $archive > $here/$STEM &
    
    done
    
    wait
    

    【讨论】:

    • 如果文件多于核心,这可能会耗尽资源;最好使用 xjobs 或 parallel 来限制同时运行的实例数。
    • 如果这是一个问题,您也可以在循环内添加一个计数器。当计数器达到最大值时,等待进程完成,然后重置计数器:(( counter++ )); if [ $counter -eq max ]; then wait; fi; counter=0
    • 是的,您可以这样做,但它的平均利用率较低(因为它会定期阻塞,直到所有内核都空闲)并且要编写更多代码(因此出错的风险更大 - 例如,你在fi之后写了counter=0,而它应该在之前)。为什么在不需要的时候花时间重新发明轮子?
    猜你喜欢
    • 1970-01-01
    • 2017-10-11
    • 2022-12-18
    • 2016-09-13
    • 2021-10-10
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 2020-04-08
    相关资源
    最近更新 更多