xargs
es la solución más flexible para dividir la salida en argumentos de comando.
También es muy legible por humanos y fácil de usar debido a su sencilla parametrización.
El formato es xargs -n $NUMLINES mycommand
.
Por ejemplo, a echo
cada línea individual en un archivo /tmp/tmp.txt
harías:
cat /tmp/tmp.txt | xargs -n 1 echo
O a diff
cada par sucesivo de archivos enumerados como líneas en un archivo del nombre anterior que haría:
cat /tmp/tmp.txt | xargs -n 2 diff
El -n 2
instruye xargs
para consumir y pasar como argumentos separados dos líneas de lo que ha canalizado a la vez.
Puedes personalizar xargs
para dividir en delimitadores además de retorno de carro/nueva línea.
Usa man xargs
y google para obtener más información sobre el poder de esta utilidad versátil.
La mejor manera de hacer esto es redirigir el archivo al bucle:
# Basic idea. Keep reading for improvements.
FILE=test
while read CMD; do
echo "$CMD"
done < "$FILE"
Una redirección con < "$FILE"
tiene algunas ventajas sobre cat "$FILE" | while ...
. Evita un uso inútil de cat, ahorrando un proceso hijo innecesario. También evita una trampa común en la que el ciclo se ejecuta en una subcapa. En Bash, comandos en un |
la tubería se ejecuta en subcapas, lo que significa que las asignaciones de variables se pierden después de que finaliza el bucle. Redirección con <
no tiene ese problema, por lo que podría usar $CMD
después del bucle o modificar otras variables dentro del bucle. También, de nuevo, evita procesos secundarios innecesarios.
Hay algunas mejoras adicionales que podrían realizarse:
- Agregar
IFS=
por lo queread
no recortará los espacios en blanco iniciales y finales de cada línea. - Agregar
-r
aread
para evitar que las barras invertidas se interpreten como secuencias de escape. - En minúsculas
CMD
yFILE
. La convención de Bash es que solo las variables de shell internas y ambientales están en mayúsculas. - Utilice
printf
en lugar deecho
que es más seguro si$cmd
es una cadena como-n
, queecho
interpretaría como una bandera.
file=test
while IFS= read -r cmd; do
printf '%s\n' "$cmd"
done < "$file"
Lo que tienes es canalizar el texto "cat test"
en el bucle.
Solo quieres:
cat test | \
while read CMD; do
echo $CMD
done