La tubería (|) conecta la salida de un comando con la entrada del siguiente. Pero muchos
comandos no leen de la entrada estándar (stdin): esperan argumentos.
rm, grep,
chmod o wc
no hacen nada útil si les envías datos por la entrada estándar (necesitan que les
pases los archivos como argumentos).
xargs resuelve eso: lee líneas de la entrada estándar y
las convierte en argumentos para el comando que le indiques.
echo -e "uno\ndos\ntres" | xargs echo
Resultado: uno dos tres. Las tres líneas se pasan como tres argumentos a echo.
El caso más habitual es combinarlo con find:
find . -name "*.log" | xargs grep "error"
find devuelve una lista de archivos, uno por línea. xargs los convierte en argumentos
de grep. El resultado es equivalente a grep "error" archivo1.log archivo2.log ...
pero sin tener que escribir los nombres a mano.
Lo mismo para borrar:
find . -name "*.tmp" | xargs rm
Sin xargs, find . -name "*.tmp" | rm no funciona porque rm no lee de la entrada estándar.
Cuando necesitas controlar dónde va el argumento dentro del comando (no solo al final),
usa -I{}:
find . -name "*.log" | xargs -I{} mv {} {}.bak
{} es el marcador de posición. Aquí xargs ejecuta un mv por cada archivo,
renombrándolo con la extensión .bak.
Con -n controlas cuántos argumentos pasa en cada ejecución:
find . -name "*.log" | xargs -n1 gzip
Ejecuta gzip una vez por archivo en lugar de pasarlos todos de golpe.
Con -P se pueden ejecutar varios procesos en paralelo. Útil cuando hay muchos archivos
y el comando tarda:
find . -name "*.log" | xargs -P4 -n1 gzip
Lanza hasta 4 procesos gzip simultáneos en lugar de uno tras otro.
xargs también resuelve un problema práctico: la consola tiene un límite en la longitud de
la línea de comandos. Si tienes miles de archivos, rm *.log puede fallar con “argument
list too long”. xargs los procesa en lotes y el error desaparece.