Primeiro de tudo, não use ls
output como uma lista de arquivos . Use a expansão do shell ou find
. Veja abaixo as possíveis conseqüências do uso indevido de ls + xargs e um exemplo de uso adequado de xargs
.
1. Maneira simples: para loop
Se você quiser processar apenas os arquivos em A/
, um simples loop for
deve ser suficiente:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 Por que não ls | xargs
?
Veja um exemplo de como as coisas podem se tornar ruins se você usar ls
com xargs
para o trabalho. Considere o seguinte cenário:
-
primeiro, vamos criar alguns arquivos vazios:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat $ touch A/mypreciousfile.dat $ touch A/mypreciousfile.dat.ans
-
veja os arquivos e eles não contêm nada:
$ ls -1 A/ mypreciousfile.dat mypreciousfile.dat with junk at the end.dat mypreciousfile.dat.ans $ cat A/*
-
execute um comando mágico usando
xargs
:$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
-
o resultado:
$ cat A/mypreciousfile.dat TRICKED with junk at the end.dat.ans $ cat A/mypreciousfile.dat.ans TRICKED
Você acabou de substituir os mypreciousfile.dat
e mypreciousfile.dat.ans
. Se houvesse algum conteúdo nesses arquivos, teria sido apagado.
2. Usando xargs
: o caminho correto com find
Se você quiser insistir em usar xargs
, use -0
(nomes com terminação nula):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Observe duas coisas: 1: dessa forma, você criará arquivos com .dat.ans
ending; 2: este irá quebrar se algum nome de arquivo contiver um sinal de cotação ( "
).
Ambos os problemas podem ser resolvidos de maneira diferente da invocação do shell:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
3. Tudo feito dentro de find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
Isso, novamente, produz arquivos .dat.ans
e será interrompido se os nomes dos arquivos contiverem "
. Para fazer isso, use bash
e altere a maneira como ele é invocado:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans'" {} \;