Aprende leyendo en orden

xargs — Construir comandos desde la entrada estándar

Coloca la entrada estándar como argumentos con echo a b | xargs echo, ejecuta palabra por palabra con -n1, inserta valores en {} con -I{}, y procesa en lote find . -name '*.log' | xargs — con diagramas y una terminal en vivo.

Convertir la entrada estándar en argumentos — xargs y -n1

Un pipe pasa la salida del comando anterior como entrada estándar del siguiente comando. Pero rm y echo no leen la entrada estándar — solo actúan sobre los valores escritos como argumentos. xargs es el comando que toma lo que recibe en la entrada estándar y lo reorganiza como argumentos para el comando que escribes después de él, así que con echo a b | xargs echo, la a y la b se convierten en argumentos del echo final.

Por defecto, xargs pasa las palabras que recibe a una sola ejecución, agrupadas todo lo posible. Añade -n1 y las separa, ejecutando el comando una vez por palabra.

SintaxisQué hace
| xargsColoca la entrada como argumentos y ejecuta el comando
xargs -n1Ejecuta el comando una vez por argumento
xargs -I{}Reemplaza {} con la entrada y la inserta donde quieras
find ... | xargsEjecuta un solo lote de procesamiento sobre lo encontrado
| xargs echo rmImprime el comando que se ejecutaría, para comprobarlo primero
xargs reorganiza la entrada como argumentos
echo a b centrada estándara b c| xargs echo| xargs -n1 echoecho a b cagrupado, 1 ejec.echo a / b / c1 palabra, 3 ejec.salidapásalo por pipepásalo por pipeejecuta una vezejecuta por palabra
La salida de echo se pasa por pipe a xargs como entrada estándar y se reorganiza en argumentos. Una ejecución agrupada, o tres ejecuciones palabra por palabra — esa es la diferencia que marca -n1.
printf 'one two three\n' | xargs echo got:        # got: one two three (agrupado, 1 ejec.)
printf 'one\ntwo\nthree\n' | xargs -n1 echo item:  # item: one / item: two / item: three

① Crea un archivo fuente de 3 líneas con printf 'red\ngreen\nblue\n' > colors.txt.

② Pasa por pipe la salida de cat colors.txt a xargs, colocando las palabras como argumentos de echo para imprimirlas todas en una sola ejecución agrupada.

③ Pasa la misma entrada a xargs con la opción que la separa palabra por palabra, y confirma que echo se ejecuta tres veces, una línea cada vez. (Cuando lo ejecutes correctamente, aparecerá una explicación).

Linux console
0 / 3 completado(s)
Loading Linux Terminal...

La cadena de reemplazo y la integración con find — -I{}

xargs -I{} construye el comando insertando cada línea de la entrada en la posición de `{}`. Como {} puede ir donde quieras, incluso en medio del comando, puedes ejecutar una forma como echo file_{}.txt — con texto fijo alrededor del valor — línea por línea.

Cuando quieres ejecutar algo sobre los archivos que find encuentra, la forma find ... | xargs es la habitual. xargs coloca como argumentos las rutas que find imprime y ejecuta un solo lote de procesamiento sobre los resultados de la búsqueda. Combínalo con -I{} y puedes procesar cada ruta encontrada insertándolas una a una en `{}`.

Procesar lo que find encuentra con xargs
find . -name '*.log'a.logb.log| xargs -I{} echo {}inserta cada líneaen {}echo a.logecho b.logimprime rutaspásalo por pipeejecuta línea 1ejecuta línea 2
Las rutas que find imprime se pasan a xargs como una línea = un elemento, y -I{} inserta cada una en `{}` y las ejecuta una a una.
printf 'alpha\nbeta\n' | xargs -I{} echo 'name = {}'   # name = alpha / name = beta
mkdir -p logs                                          # crea el directorio fuente
touch logs/a.log logs/b.log                             # crea 2 archivos
find logs -name '*.log' | xargs -I{} echo 'found {}'    # found logs/a.log / found logs/b.log

① Añade la opción de cadena de reemplazo a printf 'cat\ndog\n' | xargs e imprime cada entrada insertada en el {} de pet = {}.

② Crea un directorio con mkdir -p data, luego crea dos archivos con touch data/x.txt data/y.txt.

③ Pasa por pipe la salida de find data -name '*.txt' a xargs y usa la cadena de reemplazo para insertar cada ruta en el {} de echo 'hit {}'.

④ Ejecuta también el find data -name '*.txt' | xargs echo simple y compáralo con la forma en la que, sin -I{}, las rutas se alinean al final.

Linux console
0 / 5 completado(s)
Loading Linux Terminal...

Procesar uno a uno — elegir entre -n1 y -I{}

Tanto -n1 como -I{} ejecutan el comando uno a uno, pero difieren en dónde va el valor y cómo se separa la entrada. -n1 pasa palabras (trozos separados por espacios o saltos de línea) una a una como argumentos finales del comando. -I{} toma líneas una a una y las inserta en la posición donde escribiste `{}`.

Usa `-n1` cuando solo necesitas el valor al final, y `-I{}` cuando quieres texto fijo alrededor del valor, como {}.bak.

Aspecto`-n1``-I{}`
Dónde va el valorSe alinea al final del comandoVa donde escribiste {}
Unidad de separaciónPalabras (por espacios/saltos de línea)Líneas (una línea = un elemento)
Mejor paraSolo pasar argumentos por turnoConstruir una forma con texto fijo alrededor del valor
printf 'a\nb\n' | xargs -n1 echo prefix       # prefix a / prefix b (al final)
printf 'a\nb\n' | xargs -I{} echo {}_done      # a_done / b_done (insertado en medio)

① Añade la opción que ejecuta palabra por palabra a printf 'log1\nlog2\n' | xargs, pasándolas una a una como argumentos de echo file.

② Pasa la misma entrada a xargs y usa la opción de cadena de reemplazo para insertarlas en el {} de echo {}.bak.

③ Compara cómo cambia la salida entre alinearse al final y ser insertada en medio del comando.

Linux console
0 / 2 completado(s)
Loading Linux Terminal...

Procesamiento en lote en la práctica — comprueba antes de ejecutar

En el trabajo real, usas xargs para copias en lote y borrados en lote sobre los objetivos que find recopila. Como -I{} puede insertar el mismo valor en dos o más sitios, funciona con comandos que toman dos argumentos como cp origen destino, permitiéndote crear copias de seguridad "nombre original + .bak" todas a la vez.

No ejecutes de golpe operaciones irreversibles como rm. Si ejecutas xargs echo rm antes de xargs rm, el comando que se ejecutaría solo se imprime y no se borra nada. Comprueba los objetivos listados, luego quita el echo y ejecútalo de verdad — este enfoque de dos pasos, comprobar y luego ejecutar, es la forma segura de proceder.

Comprobar un borrado en lote imprimiéndolo antes de ejecutar
find . -name '*.tmp'a.tmpb.tmp| xargs echo rm| xargs rmrm a.tmp b.tmpsolo lo imprimeborra ambosarchivos a la vezimprime objetivos① comprueba antes② una vez verificadono borra nadaejecuta de verdad
Para operaciones irreversibles, mete un echo antes de rm para comprobar los objetivos imprimiéndolos primero, y luego ejecuta.
mkdir -p cache
touch cache/a.tmp cache/b.tmp
find cache -name '*.tmp' | xargs echo rm   # solo imprime rm cache/a.tmp cache/b.tmp
find cache -name '*.tmp' | xargs rm        # ejecuta de verdad una vez verificado

① Crea un directorio de trabajo con mkdir -p work, luego crea dos archivos fuente con touch work/note1.txt work/note2.txt.

② Pasa por pipe la salida de find work -name '*.txt' a xargs y usa la cadena de reemplazo para copiar cada archivo a "el nombre original con .bak añadido".

③ Confirma con ls work que se han añadido dos archivos .bak.

④ Pasa la salida de find work -name '*.bak' a xargs, mete un echo antes del comando de borrado, y comprueba el comando de borrado que se ejecutaría imprimiéndolo solamente.

⑤ Si los objetivos listados parecen correctos, quita el echo, borra los archivos .bak todos a la vez, y confirma con ls work de nuevo que han desaparecido.

Linux console
0 / 6 completado(s)
Loading Linux Terminal...
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Cuál describe correctamente lo que hace xargs?

Pregunta 2¿Cómo se comporta printf 'a\nb\nc\n' | xargs -n1 echo?

Pregunta 3¿Qué representa {} en xargs -I{}?