Primeiro de tudo, não use a ls
saída como uma lista de arquivos . Use expansão de shell ou find
. Veja abaixo as possíveis consequências do uso indevido de ls + xargs e um exemplo de xargs
uso adequado .
1. Maneira simples: para loop
Se você deseja processar apenas os arquivos abaixo A/
, um for
loop simples deve ser suficiente:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 Por que não ls | xargs
?
Aqui está um exemplo de quão ruim as coisas podem virar se você usar ls
com xargs
para o trabalho. Considere um cenário a seguir:
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
Então, você acabou de substituir ambos mypreciousfile.dat
e mypreciousfile.dat.ans
. Se houvesse algum conteúdo nesses arquivos, ele teria sido apagado.
2. Usando xargs
: da maneira correta com find
Se você quiser insistir em usar xargs
, use -0
(nomes terminados em nulo):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Observe duas coisas:
- Dessa forma, você criará arquivos com
.dat.ans
final;
- isso será interrompido se algum nome de arquivo contiver um sinal de aspas (
"
).
Ambos os problemas podem ser resolvidos por diferentes formas de invocação de shell:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
3. Tudo feito dentro find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
Isso, novamente, produz .dat.ans
arquivos e será interrompido se os nomes dos arquivos contiverem "
. Para fazer isso, use bash
e altere a maneira como é chamado:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;