Bash 循环遍历两组文件

Bash 循环遍历两组文件

我正在尝试编写一个 bash 脚本,它可以迭代两个文件夹,并将文件运行到 python 程序中。 python 程序接受两个输入文件(每个文件夹中对应的文件)并输出一个文件。

它看起来有点像这样:

folder 1/
    Run_1.out
    Run_2.out
    Run_3.out
    ...
folder 2/
    Sym_1.g0.out
    Sym_2.g0.out
    Sym_3.g0.out
    ...

python 程序接受相应的输入(例如Run_1.outSym_1.g0.out)并输出一个文件,如下所示:

    NOCI.py Run_1.out Sym_1.g0.out outputfile

当通过终端使用一对文件时,python 程序工作正常,但由于我有 360 对文件,我想我应该使用脚本。到目前为止,我已经尝试编写两个 for 循环,但它似乎不起作用:

    #!/bin/bash
    FILE1=*.out
    FILE2=*.g0.out
    for i in $FILE1
    do
        for j in $FILE2
            do
                NOCI.py $i $j ${i}_${outputfile}
        done
    done

答案1

匹配folder 1/Run_1.outfolder 2/Sym_1.g0.out, 依此类推 360 对:

for n in {1..360}
do
    NOCI.py "folder 1/Run_$n.out" "folder 2/Sym_$n.g0.out" outputfile
done

或者,如果配对的文件不按顺序排列,您可以挑选文件Run_N.out并关联相应的Sym_N.g0.out文件:

for r in "folder 1/Run_"*.out
do
    n="${r#folder 1/Run_}"; n="${n%.out}"
    s="folder 2/Sym_$n.out"
    NOCI.py "$r" "$s" outputfile
done

答案2

zshbash比此类任务更适合:

#! /bin/zsh -
files1=(1/*.out(n)) files2=(2/*.go.out(n))
for f1 f2 (${files1:^files2}) NOCI.py $f1 $f2 3/$f1:t:r+$f2:t
  • (n)对 glob 进行数字排序,以便按数字顺序处理它们(其中Run_10位于 和 之间Run_9Run_11而不是介于它Run_1Run_2没有它之间)。
  • ${array1:^array2}:压缩两个数组
  • $file:t:文件的尾部(基本名称)
  • $filr:r:根部分(删除扩展名)。

所以我们最终运行:

NOCI.py 1/Run_1.out 2/Sym_1.g0.out 3/Run_1+Sym_1.g0.out
NOCI.py 1/Run_2.out 2/Sym_2.g0.out 3/Run_2+Sym_2.g0.out
...

答案3

使用 GNU Parallel,您可以执行以下操作:

parallel NOCI.py {1} {2} {1.}{2.}.output ::: Folder1/* ::: Folder2/*

默认情况下,每个 CPU 线程并行运行一个作业。

要查看将运行什么,请使用--dry-run

parallel --dry-run NOCI.py {1} {2} {1.}{2.}.output ::: Folder1/* ::: Folder2/*

GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。

如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:

简单的调度

相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

GNU 并行调度

安装

出于安全原因,您应该使用软件包管理器安装 GNU Parallel,但如果 GNU Parallel 未针对您的发行版打包,您可以进行个人安装,这不需要 root 访问权限。这样做可以在 10 秒内完成:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

对于其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解更多

查看更多示例:http://www.gnu.org/software/parallel/man.html

观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

浏览本教程:http://www.gnu.org/software/parallel/parallel_tutorial.html

读了这本书:https://doi.org/10.5281/zenodo.1146014

注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel

相关内容