Bash 迭代文件对

Bash 迭代文件对

我有一个目录,其中包含一堆名称类似于 的文件a04x.txt,每个文件都有一个相应的b04y.txt文件。我需要能够对每对文件运行一些命令,并c04z.txt为每对文件生成一个附加文件。

文件中的实际数字相当大且非常稀疏,因此简单地迭代从 1 到 99 的所有数字或类似的数字是行不通的。

目前我使用以下方法来处理该任务,但似乎是一个足够常见的任务,应该有一种更短/更好的方法来完成它:

for num in ./a*x.txt
do
  num="${num##*/a}"
  num="${num%x.txt}"

  my_command a${num}x.txt b${num}y.txt c${num}z.txt
done

a${num}x.txt理想情况下,当存在或b${num}y.txt文件不具有相同编号的匹配文件时,我还希望收到警告。我还想要一种简单的方法,能够将文件集通过管道传输到,xargs或者parallel这样我就可以让它同时处理多组文件。

有一个更好的方法吗?

答案1

GNU 并行有一种方法可以做到这一点,并且作为奖励并行运行命令:

$ parallel my_command {} \
                      {= s/a([0-9]+)x.txt/b\1y.txt/ =} \
                      {= s/a([0-9]+)x.txt/c\1z.txt/ =} \
           ::: a*x.txt

这些替换是 Perl 代码。换行只是为了便于阅读——这是一行行。

答案2

  1. 一种方法是做

    for afile in a*x.txt
    do
        bfile=${afile/a/b}; bfile=${bfile/x.txt/y.txt}
        cfile=${afile/a/c}; cfile=${cfile/x.txt/z.txt}
    
        my_command "$afile" "$bfile" "$cfile"
    done
    

    尽管我认为这并不是一个很大的改进,并且在像afoox.txtbarx.txt.另请注意,这是 bash 特有的功能;它可能无法在其他符合 POSIX 标准的 shell 中工作(与 POSIX 指定的##和不同)。%

  2. 这件事说起来很简单

        if [ -f "$bfile" ]
        then
            my_command "$afile" "$bfile" "$cfile"
        else
            echo Error
        fi
    

    捕获a文件异常值(例如,a17x.txt没有相应的b17y.txt)。

  3. 如果你把

    for afile               # with no list, defaults to "$@"; i.e., the script’s arguments
    do
        bfile=${afile/a/b}; bfile=${bfile/x.txt/y.txt}
        cfile=${afile/a/c}; cfile=${cfile/x.txt/z.txt}
    
        if [ -f "$bfile" ]
        then
            my_command "$afile" "$bfile" "$cfile"
        else
            echo Error
        fi
    done
    

    到脚本中,然后您可以使用文件名列表作为参数运行该脚本,它将处理它们。然后您可以通过或运行该脚本。anumx.txtxargsparallel

  4. 作为上述过程的一部分检查b文件异常值(例如,b42y.txt 没有相应的a42x.txt)并不简单,但很容易执行单独的循环:

    for bfile in b*y.txt
    do
        afile=${bfile/b/a}; afile=${afile/y.txt/x.txt}
        if [ ! -f "$afile" ]
        then
            echo Error
        fi
    done
    

相关内容