ファイル名の一部を標準入力からの入力に置き換えるにはどうすればよいでしょうか?

ファイル名の一部を標準入力からの入力に置き換えるにはどうすればよいでしょうか?

ids.txt次のようなエントリがいくつかあるファイルがあるとします。

foo
bar
bam
...

たとえば、これを入力として使用して、、、、、... などのfoo_1.gzファイル名に ID が含まれるいくつかのファイルに対してコマンドを実行したいと思います。foo_2.gzbar_1.gzbar_2.gz

{}次のように別のコマンドで動作しているのを確認したので、入力を参照しようとしました。

cat ids.txt | xargs my.command --input1 {}_1.gz --input2 {}_2.gz 

しかし、常にこのエラーが発生します:

{}_1.gz no such file or directory

catからの入力を文字列として扱い、それを の入力ファイル名に自動的に挿入する方法はありますかmy.command?

また、問題は、my.command毎回 2 つの入力ファイルが必要になるため、 の代わりに実際のファイル名のリストを使用することができないことですids.txt

答え1

ここではオプションを使用する必要があります-I:

$ cat ids.txt | xargs -I{} echo my.command --input1 {}_1.gz --input2 {}_2.gz 
my.command --input1 foo_1.gz --input2 foo_2.gz
my.command --input1 bar_1.gz --input2 bar_2.gz
my.command --input1 bam_1.gz --input2 bam_2.gz

あるいは、シェル ループを使用します。

while read id; do 
    my.command --input1 "${id}"_1.gz --input2 "${id}"_2.gz
done < ids.txt

これは、ID に空白やバックスラッシュが含まれていないことを前提としています。含まれている場合は、代わりに以下を使用します。

while IFS= read -r id; do 
    my.command --input1 "${id}"_1.gz --input2 "${id}"_2.gz
done < ids.txt

最後に、1 行に 2 つのファイル名を含むリストを使用することもできます。

$ cat ids.txt
foo_1.gz foo_2.gz
bar_1.gz bar_2.gz
bam_1.gz bam_2.gz

今:

while read file1 file2; do
    my.command --input1 "$file1" --input2 "$file2"
done < ids.txt

関連情報