Como substituir parte de um nome de arquivo pela entrada do stdin?

Como substituir parte de um nome de arquivo pela entrada do stdin?

Digamos que eu tenha um arquivo ids.txtcom diversas entradas como

foo
bar
bam
...

por exemplo. Eu gostaria de usar isso como entrada para executar um comando em alguns arquivos contendo os IDs no nome do arquivo, como foo_1.gz, foo_2.gz, bar_1.gz, bar_2.gz, ... e assim por diante.

Tentei me referir à entrada {}como vi isso funcionando com outro comando, assim:

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

mas sempre me dá esse erro:

{}_1.gz no such file or directory

Existe alguma maneira de tratar a entrada catcomo strings de caracteres e inseri-las automaticamente nos nomes dos arquivos de entrada para my.command?

O problema também é que my.commandprecisa de dois arquivos de entrada de cada vez, então não posso simplesmente usar uma lista com os nomes reais dos arquivos em vez do arquivo ids.txt.

Responder1

Você precisa usar a -Iopção aqui:

$ 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

Alternativamente, use um loop de shell:

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

Isso pressupõe que seus IDs não tenham espaços em branco ou barras invertidas. Se puderem, use isto:

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

Finalmente, você também pode usar uma lista com dois nomes de arquivos por linha:

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

Agora:

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

informação relacionada