gnu parallel 并行化 for 循环

问题描述 投票:0回答:1

我已经看到了有关此主题的几个问题,但我缺乏将其转化为我的具体问题的能力。我有一个 for 循环,它循环遍历子目录,然后对每个目录内的压缩文本文件执行 .sh 脚本。我想并行化这个过程,但我正在努力应用 gnu 并行。

这是我的循环:

for d in ./*/ ; do (cd "$d" && script.sh); done

我知道我需要将一个列表输入到并行中,所以我一直在尝试这个:

ls -d */ | parallel cd && script.sh

虽然这似乎开始了,但当 gzip 尝试解压缩目录中的一个 txt 文件时,我收到错误,说该文件不存在:

gzip: *.txt.gz: No such file or directory

但是,当我运行原始的 for 循环时,除了需要一个世纪才能完成之外,我没有任何问题。另外,我在使用并行时只遇到一次 gzip 错误,考虑到我有超过 1000 个子目录,这很奇怪。

我的问题是:

  1. 如何让 Parallel 在我的情况下工作?如何并行地将 .sh 脚本的应用程序并行化到其自己的子目录中的 1000 个文件?即-我的问题的解决方案是什么?我一定要进步。

  2. 我错过了什么?语法、循环、脚本错误?我想学习。

  3. Parallel 实际上是否尝试并行运行所有这些 .sh 脚本?为什么每个 .txt.gz 文件都没有出现错误?

  4. 并行是应用程序的最佳选择吗?还有其他更适合我需求的选择吗?

bash ubuntu parallel-processing gnu gnu-parallel
1个回答
17
投票

两个问题:

  1. 在:

     ls -d */ | parallel cd && script.sh
    

并行的只是

cd
,而不是
script.sh
。如果没有错误,在所有
script.sh
作业运行之后,
parallel cd
仅执行一次。它等同于:

    ls -d */ | parallel cd
    if [ $? -eq 0 ]; then script.sh; fi
  1. 您没有将目标目录传递给
    cd
    。因此,
    parallel
    执行的只是
    cd
    ,它只是将当前目录更改为您的主目录。最后的
    script.sh
    在当前目录(调用命令的位置)中执行,其中可能没有
    *.txt.gz
    文件,因此会出现错误。

您可以通过以下方式检查第一个问题的效果:

$ mkdir /tmp/foobar/{a..c} && cd /tmp/foobar
$ ls -d */ | parallel cd && pwd
/tmp/foobar

pwd
的输出仅打印一次,即使您有多个输入目录。您可以通过引用命令来修复它,然后检查第二个问题:

$ ls -d */ | parallel 'cd && pwd'
/homes/myself
/homes/myself
/homes/myself

您应该看到与输入目录一样多的

pwd
输出,但它始终是相同的输出:您的主目录。您可以使用替换为当前输入的
{}
替换字符串来解决第二个问题。检查一下:

$ ls -d */ | parallel 'cd {} && pwd'
/tmp/foobar/a
/tmp/foobar/b
/tmp/foobar/c

现在,您应该在输出中正确列出所有输入目录。

对于您的具体问题,这应该有效:

ls -d */ | parallel 'cd {} && script.sh'
© www.soinside.com 2019 - 2024. All rights reserved.