bash脚本的新手。我有一个shell脚本,它通过终端在Matlab中运行多个纵向图像处理功能。我想在终端中并行化该过程。
以下是它如何运行的简短示例:./ script.sh * .nii -surface -m /Applications/MATLAB_R2018b.app/bin/matlab
* .nii是指在不同时间拍摄的单个主体的图像(即subj1img1 subj1img2 subj3img3)。在我的案例中,每个主题有三个图像。因此,在每次运行中,脚本都会遍历单个主题的所有图像。
我想并行化这个过程,以便我可以同时为多个主题运行此脚本。通过我的小经验阅读GNU并行,我无法弄清楚我需要编写的代码来实现它。如果有人有任何建议,我真的很感激。
解决办法:GNU并行
有一些方法可以并行运行未构建到Bash中的命令。GNU Parallel是一个可以做到这一点的工具。
GNU Parallel,顾名思义,可用于并行构建和运行命令。您可以使用不同的参数运行相同的命令,无论它们是文件名,用户名,主机名还是从文件读取的行。GNU Parallel提供了对许多最常见操作(输入行,输入行的各个部分,指定输入源的不同方式等)的简写引用。Parallel可以将xargs或feed命令从其输入源替换为几个不同的Bash实例。
有关完整说明,请参阅GNU Parallel文档。一些例子应该简要介绍它的用法。
例如,很容易将xargs替换为gzip当前目录及其子目录中的所有html文件:
find . -type f -name '*.html' -print | parallel gzip
如果需要保护特殊字符(如文件名中的换行符),请使用find的-print0选项和parallel的-0选项。
当文件数太大而无法使用一个mv调用进行处理时,可以使用Parallel从当前目录移动文件:
ls | parallel mv {} destdir
如您所见,{}被替换为从标准输入读取的每一行。虽然使用ls在大多数情况下都可以使用,但是处理所有文件名还不够。如果您需要在文件名中容纳特殊字符,则可以使用
find . -depth 1 \! -name '.*' -print0 | parallel -0 mv {} destdir
如上所述。
这将运行与当前目录中的文件一样多的mv命令。您可以通过添加-X选项来模拟并行xargs:
find . -depth 1 \! -name '.*' -print0 | parallel -0 -X mv {} destdir
GNU Parallel可以替换在从文件读取的行上操作的某些常用习语(在这种情况下,每行列出一个文件名):
while IFS= read -r x; do
do-something1 "$x" "config-$x"
do-something2 < "$x"
done < file | process-output
更简洁的语法让人联想到lambdas:
cat list | parallel "do-something1 {} config-{} ; do-something2 < {}" |
process-output
Parallel提供了一个内置机制来删除文件扩展名,这有助于批处理文件转换或重命名:
ls *.gz | parallel -j+0 "zcat {} | bzip2 >{.}.bz2 && rm {}"








暂无数据