En primer lugar, no use la ls
salida como una lista de archivos . Usar expansión de concha o find
. Vea a continuación las posibles consecuencias del mal uso de ls + xargs y un ejemplo de xargs
uso adecuado .
1. Forma simple: para bucle
Si desea procesar solo los archivos A/
, entonces un simple for
bucle debería ser suficiente:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
2. pre1 ¿ Por qué no ls | xargs
?
He aquí un ejemplo de lo mal que puede resultar si se utiliza ls
con xargs
para el trabajo. Considere un siguiente escenario:
primero, creemos algunos archivos vacíos:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
$ touch A/mypreciousfile.dat
$ touch A/mypreciousfile.dat.ans
ver los archivos y que no contienen nada:
$ ls -1 A/
mypreciousfile.dat
mypreciousfile.dat with junk at the end.dat
mypreciousfile.dat.ans
$ cat A/*
ejecuta un comando mágico usando xargs
:
$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
el resultado:
$ cat A/mypreciousfile.dat
TRICKED with junk at the end.dat.ans
$ cat A/mypreciousfile.dat.ans
TRICKED
Así que has logrado sobrescribir ambas mypreciousfile.dat
y mypreciousfile.dat.ans
. Si hubiera algún contenido en esos archivos, se habría borrado.
2. Utilizando xargs
: la forma correcta con find
Si desea insistir en usar xargs
, use -0
(nombres con terminación nula):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
Note dos cosas:
- de esta manera creará archivos con
.dat.ans
finalización;
- esto se romperá si algún nombre de archivo contiene un signo de comillas (
"
).
Ambos problemas pueden resolverse mediante diferentes formas de invocación de shell:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
3. Todo hecho dentro find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
Esto, nuevamente, produce .dat.ans
archivos y se romperá si contienen nombres de archivos "
. Para bash
hacerlo , use y cambie la forma en que se invoca:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;