GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo pasar la salida del comando como múltiples argumentos a otro comando

Para completar, también mencionaré la sustitución de comandos y explicaré por qué esto no se recomienda:

cp $(grep -l "pattern" input) directory/

(La sintaxis de acento grave cp `grep -l "pattern" input` directory/ es más o menos equivalente, pero es obsoleto y difícil de manejar; no uses eso.)

Esto fallará si la salida de grep produce un nombre de archivo que contiene espacios en blanco o un metacarácter de shell.

Por supuesto, está bien usar esto si sabe exactamente qué archivo nombra el grep puede producir, y he comprobado que ninguno de ellos es problemático. Pero para un guión de producción, no use esto.

De todos modos, para el escenario del OP, donde debe referirse a cada coincidencia individualmente y agregarle una extensión, el xargs o while read las alternativas son superiores de todos modos.

En el peor de los casos (es decir, nombres de archivo problemáticos o no especificados), pase las coincidencias a una subcapa a través de xargs :

grep -l "pattern" input |
xargs -r sh -c 'for f; do cp "$f" "$f.bac"; done' _

... donde obviamente el script dentro del for bucle podría ser arbitrariamente complejo.

En el caso ideal, el comando que desea ejecutar es lo suficientemente simple (o versátil) como para que simplemente pueda pasarle una lista arbitrariamente larga de nombres de archivo. Por ejemplo, GNU cp tiene un -t opción para facilitar este uso de xargs (el -t le permite poner el directorio de destino primero en la línea de comando, para que pueda poner tantos archivos como desee al final del comando):

grep -l "pattern" input | xargs cp -t destdir

que se expandirá en

cp -t destdir file1 file2 file3 file4 ...

para tantas coincidencias como xargs puede caber en la línea de comando de cp , repetido tantas veces como sea necesario para pasar todos los archivos a cp . (Desafortunadamente, esto no coincide con el escenario del OP; si necesita cambiar el nombre de cada archivo mientras copia, debe pasar solo dos argumentos por cp invocación:el nombre del archivo de origen y el nombre del archivo de destino para copiarlo.)

En otras palabras, si usa la sintaxis de sustitución de comandos y grep produce un realmente larga lista de coincidencias, corre el riesgo de toparse con ARG_MAX y errores de "Lista de argumentos demasiado larga"; pero xargs evitará específicamente esto copiando en su lugar solo tantos argumentos como pueda pasar con seguridad a cp a la vez y ejecutando cp varias veces si es necesario.


Puedes usar xargs :

grep 'pattern' input | xargs -I% cp "%" "%.bac"

Puedes usar $() para interpolar la salida de un comando. Entonces, podrías usar kill -9 $(grep -hP '^\d+$' $(ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }')) si quisieras.


Además de la buena respuesta de Chris Jester-Young, diría que xargs también es una buena solución para estas situaciones:

grep ... `ls -lad ... | awk '{ print $9 }'` | xargs kill -9

lo hará Todos juntos:

grep -hP '^\d+$' `ls -lad /dir/*/pid | grep -P '/dir/\d+/pid' | awk '{ print $9 }'` | xargs kill -9

Linux
  1. ¿Cómo encontrar múltiples cadenas en archivos?

  2. ¿Cómo capturar la salida de un comando superior en un archivo en Linux?

  3. Salida de comando de Linux como parámetro de otro comando

  4. ¿Cómo concatenar varias líneas de salida en una sola línea?

  5. ¿Cómo puedo recorrer la salida de un comando de shell?

Cómo asignar la salida de un comando de Linux a una variable

Cómo pasar la contraseña al comando SCP en Linux

Cómo pasar la contraseña al comando SSH en Linux

Cómo usar grep en Linux

¿Cómo agregar la salida a un archivo?

Cómo pasar la salida del comando como varios argumentos a otro comando