![ファイル名の一部を標準入力からの入力に置き換えるにはどうすればよいでしょうか?](https://rvso.com/image/178489/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%AE%E4%B8%80%E9%83%A8%E3%82%92%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B%E3%81%8B%E3%82%89%E3%81%AE%E5%85%A5%E5%8A%9B%E3%81%AB%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%82%88%E3%81%84%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B%3F.png)
ids.txt
次のようなエントリがいくつかあるファイルがあるとします。
foo
bar
bam
...
たとえば、これを入力として使用して、、、、、... などのfoo_1.gz
ファイル名に ID が含まれるいくつかのファイルに対してコマンドを実行したいと思います。foo_2.gz
bar_1.gz
bar_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