平行壳环

mat*_*ath 11 bash zsh shell parallel-processing

我想处理很多文件,因为我这里有一堆内核,所以我想并行处理:

for i in *.myfiles; do do_something $i `derived_params $i` other_params; done
Run Code Online (Sandbox Code Playgroud)

我知道 Makefile解决方案,但我的命令需要 shell globbing 列表中的参数。我发现的是:

> function pwait() {
>     while [ $(jobs -p | wc -l) -ge $1 ]; do
>         sleep 1
>     done
> }
>
Run Code Online (Sandbox Code Playgroud)

要使用它,只需将 & 放在作业和 pwait 调用之后,参数给出并行进程的数量:

> for i in *; do
>     do_something $i &
>     pwait 10
> done
Run Code Online (Sandbox Code Playgroud)

但这并不能很好地工作,例如,我尝试使用 for 循环转换许多文件但给我错误并留下未完成的作业。

我不敢相信这还没有完成,因为关于 zsh 邮件列表的讨论现在已经很老了。那么你知道更好的吗?

Gil*_*il' 15

makefile可以很好地解决您的问题。您可以在 shell 中对这种并行执行进行编程,但正如您所注意到的,这很难。make 的并行实现不仅会处理启动作业和检测它们的终止,还会处理负载平衡,这很棘手。

globbing 的要求不是障碍:有支持它的 make 实现。GNU make,它具有通配符扩展,例如$(wildcard *.c)和 shell 访问,例如$(shell mycommand)(在 GNU make 手册中查找函数以获取更多信息)。它是makeLinux上的默认设置,可用于大多数其他系统。这是一个 Makefile 框架,您可以根据自己的需要进行调整:

来源 = $(通配符 *.src)

全部:$(来源:.src=.tgt)

%.tgt: %.src
    do_something $< $$(derived_pa​​rams $<) >$@

运行类似make -j4并行执行四个作业,或make -j -l3将平均负载保持在 3 左右的操作。


小智 8

我不确定你的派生参数是什么样的。但是使用 GNU Parallel http://www.gnu.org/software/parallel/ 你可以这样做来为每个 CPU 核心运行一项工作:

find . | parallel -j+0 'a={}; name=${a##*/}; upper=$(echo "$name" | tr "[:lower:]" "[:upper:]");
   echo "$name - $upper"'
Run Code Online (Sandbox Code Playgroud)

如果您想要派生的只是更改 .extension,那么 {.} 可能会很方便:

parallel -j+0 lame {} -o {.}.mp3 ::: *.wav
Run Code Online (Sandbox Code Playgroud)

http://www.youtube.com/watch?v=OpaiGYxkSuQ 上观看 GNU Parallel 的介绍视频


Den*_*son 7

使用 shell 的wait命令对您不起作用吗?

for i in *
do
    do_something $i &
done
wait
Run Code Online (Sandbox Code Playgroud)

您的循环执行一个作业,然后等待它,然后执行下一个作业。如果上述方法对您不起作用,那么如果您pwaitdone.