Digamos que tengo un archivo que foo.txt
especifica N
argumentos
arg1
arg2
...
argN
que necesito pasar al comando my_command
¿Cómo uso las líneas de un archivo como argumentos de un comando?
Digamos que tengo un archivo que foo.txt
especifica N
argumentos
arg1
arg2
...
argN
que necesito pasar al comando my_command
¿Cómo uso las líneas de un archivo como argumentos de un comando?
Respuestas:
Si su shell es bash (entre otros), un atajo para
$(cat afile)
es$(< afile)
, por lo que escribiría:Documentado en la página de manual de bash en la sección 'Sustitución de comandos'.
Alternativamente, haga que su comando se lea desde stdin, entonces:
mycommand < file.txt
fuente
<
operador. Significa que el propio shell realizará la redirección en lugar de ejecutar elcat
binario por sus propiedades de redirección."$(…)"
, el contenido defile.txt
se pasaría a la entrada estándar demycommand
, no como un argumento."$(…)"
significa ejecutar el comando y devolver la salida como una cadena ; aquí el "comando" solo lee el archivo pero podría ser más complejo.Como ya se mencionó, puede usar los backticks o
$(cat filename)
.Lo que no se mencionó, y creo que es importante tener en cuenta, es que debe recordar que el shell dividirá el contenido de ese archivo según el espacio en blanco, dando cada "palabra" que encuentre a su comando como argumento. Y si bien puede encerrar un argumento de línea de comandos entre comillas para que pueda contener espacios en blanco, secuencias de escape, etc., leer del archivo no hará lo mismo. Por ejemplo, si su archivo contiene:
los argumentos que obtendrás son:
Si desea extraer cada línea como argumento, use la construcción while / read / do:
fuente
read -r
menos que desee expandir las secuencias de escape de barra diagonal inversa, y NUL es un delimitador más seguro que la nueva línea, particularmente si los argumentos que está pasando son nombres de archivos, que pueden contener nuevas líneas literales. Además, sin borrar IFS, obtiene espacios en blanco iniciales y finales borrados implícitamentei
.pasará el contenido del archivo al comando en stdin, pero eliminará las nuevas líneas, lo que significa que no puede iterar sobre cada línea individualmente. Para eso, podría escribir un script con un bucle 'for':
O (la variante multilínea):
O (variante multilínea con en
$()
lugar de``
):Referencias
fuente
< file
backticks significa que en realidad no realiza una redireccióncommand
en absoluto.command `< file`
No funciona ni en bash ni en POSIX sh; zsh es un asunto diferente, pero ese no es el tema del que trata esta pregunta).Hello World
en una línea. Lo verás primerosome_command Hello
, luegosome_command World
, nosome_command "Hello World"
osome_command Hello World
.Lo haces usando backticks:
fuente
echo "Hello * Starry * World" > file.txt
en el primer paso, obtendría al menos cuatro argumentos separados pasados al segundo comando, y probablemente más, ya que el*
s se expandiría a los nombres de los archivos presentes en el directorio actual.fork()
saliendo de una subshell con un FIFO adjunto a su stdout, luego invocando/bin/cat
como hijo de esa subshell, luego leyendo la salida a través del FIFO; compare con$(<file.txt)
, que lee el contenido del archivo en bash directamente sin subcapas ni FIFO involucrados.Si desea hacer esto de una manera robusta que funcione para todos los argumentos posibles de la línea de comando (valores con espacios, valores con líneas nuevas, valores con comillas literales, valores no imprimibles, valores con caracteres globales, etc.), se pone un poco más interesante.
Para escribir en un archivo, dada una serie de argumentos:
... reemplazar con
"argument one"
,"argument two"
, etc., según corresponda.Para leer ese archivo y usar su contenido (en bash, ksh93 u otro shell reciente con matrices):
Para leer ese archivo y usar su contenido (en un shell sin matrices; tenga en cuenta que esto sobrescribirá su lista de argumentos de la línea de comandos local, y por lo tanto, es mejor hacerlo dentro de una función, de modo que sobrescriba los argumentos de la función y no la lista global):
Tenga en cuenta que
-d
(permitir que se use un delimitador de fin de línea diferente) es una extensión que no es POSIX, y un shell sin matrices también puede no ser compatible. Si ese fuera el caso, es posible que deba usar un lenguaje que no sea shell para transformar el contenido delimitado por NUL en unaeval
forma segura:fuente
Así es como paso el contenido de un archivo como argumento a un comando:
fuente
$(<bar.txt)
(cuando se usa un shell, como bash, con la extensión adecuada).$(<foo)
es un caso especial: a diferencia de la sustitución regular de comandos, como se usa en$(cat ...)
, no se bifurca en un subshell para operar, y por lo tanto evita una gran cantidad de sobrecarga.Si todo lo que necesita hacer es convertir el archivo
arguments.txt
con contenidoen
my_command arg1 arg2 argN
entonces puede simplemente utilizarxargs
:Puede poner argumentos estáticos adicionales en la
xargs
llamada, comoxargs -a arguments.txt my_command staticArg
cuál llamarámy_command staticArg arg1 arg2 argN
fuente
En mi bash shell, lo siguiente funcionó a las mil maravillas:
donde input_file es
Como es evidente, esto le permite ejecutar múltiples comandos con cada línea desde input_file, un pequeño truco que aprendí aquí .
fuente
$(somecommand)
, ejecutará ese comando en lugar de pasarlo como texto. Del mismo modo,>/etc/passwd
se procesará como una redirección y sobrescritura/etc/passwd
(si se ejecuta con los permisos adecuados), etc.xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
y también más eficiente, ya que pasa tantos argumentos a cada shell como sea posible en lugar de comenzar un shell por línea en su archivo de entrada.cat
Después de editar la respuesta de @Wesley Rice un par de veces, decidí que mis cambios eran demasiado grandes para continuar cambiando su respuesta en lugar de escribir la mía. Entonces, ¡decidí que necesitaba escribir el mío!
Lea cada línea de un archivo y opere en él línea por línea de esta manera:
Esto viene directamente del autor Vivek Gite aquí: https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . ¡Obtiene el crédito!
Y ahora para responder a esta pregunta ahora cerrada que también tuve: ¿Es posible 'agregar' una lista de archivos de un archivo?- Aquí está mi respuesta:
Tenga en cuenta que
FILES_STAGED
es una variable que contiene la ruta absoluta a un archivo que contiene un montón de líneas donde cada línea es una ruta relativa a un archivo que me gustaría hacergit add
. Este fragmento de código está a punto de formar parte del archivo "eRCaGuy_dotfiles / útiles_scripts / sync_git_repo_to_build_machine.sh" en este proyecto, para permitir la sincronización fácil de archivos en desarrollo desde una PC (por ejemplo: una computadora que codifico) a otra (por ejemplo: un computadora más potente sobre la que construyo): https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .Referencias
Relacionado:
git add
en él: ¿Es posible `git add` una lista de archivos de un archivo?fuente