gnu并行化for循环

时间:2017-08-23 03:42:51

标签: bash ubuntu parallel-processing gnu gnu-parallel

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

这是我的循环:

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循环时,除了需要一个世纪才能完成之外我没有任何问题。另外,我在使用parallel时只得到一次gzip错误,考虑到我有超过1000个子目录,这很奇怪。

我的问题是:

  1. 如何在我的案例中使并行工作?如何并行将.sh脚本的应用程序并行化到自己子目录中的1000个文件?即 - 我的问题的解决方案是什么?我必须取得进步。

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

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

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

1 个答案:

答案 0 :(得分:5)

两个问题:

  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
    
  2. 您没有将目标目录传递给cd。因此,parallel执行的只是cd,它只是将当前目录更改为您的主目录。最后的script.sh在当前目录(从您调用命令的位置)执行,其中可能没有*.txt.gz个文件,因此出错。

  3. 您可以通过以下方式检查第一个问题的影响:

    $ mkdir /tmp/foobar && cd /tmp/foobar && mkdir a b c
    $ 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'