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にはこれを行う方法があり、ボーナスでコマンドを並列に実行します。

$ 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コードです。改行は単に可読性のためのものです。一度に1行ずつ表示されます。

答え2

  1. 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。また、これは他のPOSIX互換シェルでは機能しない可能性があります(##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
    

関連情報