Me gustaría correr:
./a.out < x.dat > x.ans
para cada uno * .dat archivo en el directorio A .
Claro, podría hacerse por bash / python / cualquier script, pero me gusta escribir sexy one-liner. Todo lo que pude alcanzar es (aún sin ningún stdout):
ls A/*.dat | xargs -I file -a file ./a.out
Pero -a en xargs no entiende reemplazar-str 'archivo'.
Gracias por ayudar.
io-redirection
xargs
Nikolay Vyahhi
fuente
fuente
Respuestas:
En primer lugar, no use la
ls
salida como una lista de archivos . Usar expansión de concha ofind
. Vea a continuación las posibles consecuencias del mal uso de ls + xargs y un ejemplo dexargs
uso adecuado .1. Forma simple: para bucle
Si desea procesar solo los archivos
A/
, entonces un simplefor
bucle debería ser suficiente:2. pre1 ¿ Por qué no
ls | xargs
?He aquí un ejemplo de lo mal que puede resultar si se utiliza
ls
conxargs
para el trabajo. Considere un siguiente escenario:primero, creemos algunos archivos vacíos:
ver los archivos y que no contienen nada:
ejecuta un comando mágico usando
xargs
:el resultado:
Así que has logrado sobrescribir ambas
mypreciousfile.dat
ymypreciousfile.dat.ans
. Si hubiera algún contenido en esos archivos, se habría borrado.2. Utilizando
xargs
: la forma correcta confind
Si desea insistir en usar
xargs
, use-0
(nombres con terminación nula):Note dos cosas:
.dat.ans
finalización;"
).Ambos problemas pueden resolverse mediante diferentes formas de invocación de shell:
3. Todo hecho dentro
find ... -exec
Esto, nuevamente, produce
.dat.ans
archivos y se romperá si contienen nombres de archivos"
. Parabash
hacerlo , use y cambie la forma en que se invoca:fuente
zsh
se usa como shell (y SH_WORD_SPLIT no está configurado), no es necesario tener en cuenta todos los casos especiales desagradables (espacios en blanco ", en el nombre del archivo, etc.). Lo trivialfor file in A/*.dat; do ./a.out < $file > ${file%.dat}.ans ; done
funciona en todos los casos.find
.Intente hacer algo como esto (la sintaxis puede variar un poco dependiendo del shell que use):
$ for i in $(find A/ -name \*.dat); do ./a.out < ${i} > ${i%.dat}.ans; done
fuente
somefile.dat.dat
y redirigir toda la salida a un solo archivo.somefile.dat.ans
las cosas de salida no se verían tan bien.-type file
sería bueno (no se puede< directory
), y esto entristece al hada inusual del nombre de archivo.Para patrones simples, el bucle for es apropiado:
Para casos más complejos en los que necesita otra utilidad para enumerar los archivos (zsh o bash 4 tienen patrones lo suficientemente potentes que rara vez necesita encontrar, pero si desea permanecer dentro del shell POSIX o usar un shell rápido como el guión, necesitará encontrar cualquier cosa no trivial), mientras que leer es más apropiado:
Esto manejará espacios, porque la lectura está (por defecto) orientada a líneas. No manejará las nuevas líneas ni las barras invertidas, porque de forma predeterminada interpreta las secuencias de escape (que en realidad le permiten pasar una nueva línea, pero find no puede generar ese formato). Muchos shells tienen la
-0
opción de leer, por lo que en esos puedes manejar todos los caracteres, pero desafortunadamente no es POSIX.fuente
Use GNU Paralelo:
Bonificación adicional: el procesamiento se realiza en paralelo.
Mire los videos de introducción para obtener más información: http://www.youtube.com/watch?v=OpaiGYxkSuQ
fuente
Creo que necesita al menos una invocación de shell en los xargs:
Editar: debe tenerse en cuenta que este enfoque no funciona cuando los nombres de los archivos contienen espacios en blanco. No puedo trabajar Incluso si usó find -0 y xargs -0 para hacer que xargs entienda los espacios correctamente, la llamada de shell -c los graznaría. Sin embargo, el OP solicitó explícitamente una solución de xargs, y esta es la mejor solución de xargs que se me ocurrió. Si el espacio en blanco en los nombres de archivo puede ser un problema, use find -exec o un bucle de shell.
fuente
ls
salida .ls
genera cosas como espacios sin escapar y ese es el problema.ls
no es bueno. Pero sexargs
puede usar de forma segura con find: consulte la sugerencia n. ° 2 en mi respuesta.No hay necesidad de complicarlo. Podrías hacerlo con un
for
bucle:el
${file%.dat}.ans
bit eliminará el.dat
sufijo del nombre de archivo del nombre de archivo$file
y en su lugar se agregará.ans
al final.fuente