Aprende leyendo en orden

xargs — construir comandos desde la entrada estándar

Este artículo forma parte del Curso de Linux, con el que dominarás desde cero habilidades prácticas de Linux, desde los comandos básicos hasta los scripts de shell.
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{}?