xargs
Pasa la salida de un comando como argumentos de otro comando.
Convierte la salida de un comando en argumentos para otro, para que puedas aplicarlo a una lista de archivos sin escribirlos uno por uno. Es el puente entre dos comandos: uno produce la lista (find, ls, grep) y el otro la usa para renombrar, mover o borrar en lote. Ya viene instalado en Debian y Ubuntu, porque forma parte de findutils, que es obligatorio del sistema.
xargs [opciones] [COMANDO [argumentos]]Con rm o mv la cosa se pone seria: los nombres se parten por espacios, así que ls | xargs rm sobre 'mi foto.jpg' intenta borrar 'mi' y 'foto.jpg'. Si por casualidad existe un archivo llamado 'mi', lo borra sin preguntar. Nunca le pases a rm la salida de ls; mejor find -print0 con xargs -0, que mantiene cada nombre entero.
Despiece
6 ejemplosContar líneas de varios archivos
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | ls | Comando | El primer comando: lista los archivos .txt de la carpeta. |
| 2 | *.txt | Argumento | El comodín de la terminal: se expande a todos los archivos que terminan en .txt. |
| 3 | | | Operador | El pipe: manda la salida de ls a la entrada de xargs. |
| 4 | xargs | Comando | Toma esos nombres y se los pasa como argumentos al comando que sigue. |
| 5 | wc | Comando | El comando que quieres aplicar a cada archivo. |
| 6 | -l | Opción | Cuenta líneas en vez de palabras o bytes. |
wc cuenta las líneas de los tres archivos y al final agrega una línea de total. Sin xargs tendrías que escribir wc -l a.txt b.txt c.txt a mano, y con muchos archivos ya no cabe ni en una línea.
Procesar un archivo por comando
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | ls | Comando | Lista los archivos .txt de la carpeta. |
| 2 | *.txt | Argumento | El comodín que se expande a los nombres de los archivos. |
| 3 | | | Operador | Pasa la lista a xargs. |
| 4 | xargs | Comando | Reparte los nombres en varios comandos. |
| 5 | -n 1 | Opción | Máximo un elemento por ejecución: el comando corre una vez por archivo. |
| 6 | wc | Comando | El comando que se aplica a cada archivo. |
| 7 | -l | Opción | Cuenta líneas. |
wc -l corre una vez por archivo y por eso ya no hay línea de total, solo el conteo de cada uno. Con -n 1 también funcionan los comandos que aceptan un solo archivo a la vez, como mv o gzip, que con la lista completa se quejan.
Que los nombres con espacios no se rompan
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | find | Comando | Busca archivos por nombre en lugar de listar una sola carpeta. |
| 2 | . | Argumento | La carpeta donde empieza la búsqueda: la actual y todo lo que tenga dentro. |
| 3 | -name '*.jpg' | Opción | Solo los archivos cuyo nombre termina en .jpg. Las comillas son para que el asterisco lo vea find y no la terminal. |
| 4 | -print0 | Opción | Muestra cada ruta terminada en un byte nulo, un separador que ningún nombre de archivo puede contener. |
| 5 | | | Operador | Pasa la lista a xargs. |
| 6 | xargs | Comando | Reparte los nombres al comando que sigue. |
| 7 | -0 | Opción | Lee los elementos terminados en byte nulo, para que cada nombre llegue entero. |
| 8 | ls | Comando | El comando que se aplica a cada nombre. |
| 9 | -1 | Opción | Un nombre por línea, sin el formato de columnas. |
Cada nombre llega completo a ls, incluso los que tienen espacios, como 'mi foto.jpg'. Si quitas el -0, xargs parte esa línea en tres y ls se queja de que no encuentra 'mi' ni 'foto'. Por eso con find siempre van juntos -print0 y -0.
Poner el nombre donde quieras dentro del comando
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | find | Comando | Busca los archivos que quieras transformar. |
| 2 | . | Argumento | La carpeta donde empieza la búsqueda. |
| 3 | -maxdepth 1 | Opción | No baja a las subcarpetas: solo revisa el primer nivel. |
| 4 | -name '*.txt' | Opción | Solo los .txt. |
| 5 | | | Operador | Pasa la lista a xargs. |
| 6 | xargs | Comando | Va a correr un cp por cada nombre recibido. |
| 7 | -I {} | Opción | El texto entre {} es el marcador que se va a sustituir por el nombre de cada archivo. |
| 8 | cp | Comando | La copia. |
| 9 | {} | Argumento | Primer marcador: el origen, o sea el archivo encontrado. |
| 10 | {}.bak | Argumento | Segundo marcador: el destino. Al pegarse al nombre, le agrega la extensión .bak. |
Cada .txt de la carpeta gana su copia .bak, sin entrar a subcarpetas. El -I {} es obligatorio: sin él, xargs pasaría el texto {} tal cual y cp fallaría.
Borrar los archivos que cumplen una condición
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | find | Comando | Busca los archivos en todo el árbol de carpetas. |
| 2 | . | Argumento | La carpeta actual, de la que cuelgan sus subcarpetas. |
| 3 | -name '*.log' | Opción | Solo los que terminan en .log. |
| 4 | -print0 | Opción | Separa los nombres con un byte nulo para que xargs no los parta. |
| 5 | | | Operador | Pasa la lista a xargs. |
| 6 | xargs | Comando | Reparte los nombres al comando que sigue. |
| 7 | -0 | Opción | Lee los nombres terminados en byte nulo. |
| 8 | rm | Comando | El que borra. Ojo: borra sin preguntar, sin mover a la papelera. |
| 9 | -f | Opción | No pregunta ni se queja por archivos que ya no existen, que es lo normal cuando rm corre en varios lotes. |
Desaparecen los .log de la carpeta actual y de sus subcarpetas, y rm no pregunta nada. Antes de correrlo así, revisa la lista: quita el rm y pon ls, o agrega -t a xargs para ver el comando completo.
Acelerar con varios comandos en paralelo
| N.º | Pieza | Tipo | Qué hace |
|---|---|---|---|
| 1 | find | Comando | Busca las imágenes en todo el árbol. |
| 2 | . | Argumento | La carpeta actual como punto de partida. |
| 3 | -name '*.jpg' | Opción | Solo los .jpg. |
| 4 | -print0 | Opción | Separa los nombres con byte nulo. |
| 5 | | | Operador | Pasa la lista a xargs. |
| 6 | xargs | Comando | Reparte los nombres, ahora en varios comandos al mismo tiempo. |
| 7 | -0 | Opción | Lee los nombres terminados en byte nulo. |
| 8 | -P 4 | Opción | Hasta cuatro procesos md5sum corriendo a la vez. |
| 9 | -n 1 | Opción | Un archivo por ejecución, para que el trabajo se reparta parejo. |
| 10 | md5sum | Comando | Calcula la huella de cada imagen; sirve para compararlas y ver si dos copias son idénticas. |
Cada jpg sale con su hash MD5. El -P 4 es lo que hace la diferencia en carpetas grandes: sin -P, xargs corre los comandos uno tras otro y con cuatro a la vez el trabajo termina bastante más rápido. Súbele mientras el equipo aguante, con -P 8 o -P $(nproc).
Opciones
Las que sí vas a usar| Opción | Qué hace |
|---|---|
| -n--max-args=N | Manda como máximo N elementos en cada ejecución del comando. Con xargs -n 1 el comando corre una vez por archivo, que es lo que casi siempre quieres. |
| -0 | Lee los elementos terminados en byte nulo (el que produce find -print0) en vez de separados por espacios. Así los archivos con espacios llegan enteros. |
| -I--replace | Define un marcador, normalmente {}, que se sustituye por cada elemento. El comando corre una vez por elemento. |
| -P--max-procs=N | Ejecuta hasta N comandos al mismo tiempo. Súbele para tareas lentas como comprimir, convertir imágenes o calcular hashes. |
| -r--no-run-if-empty | No corre el comando si la entrada no trae nada. Sin esto, un grep sin resultados puede terminar ejecutando algo como rm -rf sobre la carpeta equivocada. |
| -t--verbose | Muestra el comando completo antes de correrlo. La forma más fácil de revisar qué va a pasar antes de poner un rm debajo. |
| -d--delimiter=DELIM | Cambia el separador de la entrada. Útil cuando los datos vienen con comas, como la salida de cut o tr. |
| -a--arg-file=ARCHIVO | Lee los argumentos del archivo indicado, uno por línea, en vez de recibirlos por la entrada estándar. |
Fallas comunes
| Falla | Remedio |
|---|---|
| Pegarle los comandos como texto: echo 'ls *.txt' | xargs wc -l. | echo solo imprime palabras, así que xargs termina corriendo wc -l sobre archivos llamados 'ls' y '*.txt', y wc responde wc: ls: No such file or directory. Para pasar la salida de un comando a otro se encadena con el pipe: ls *.txt | xargs wc -l. |
| No usar -0 con find y tener archivos con espacios en la carpeta. | xargs parte cada línea por espacios, así que 'mi foto.jpg' se convierte en tres argumentos y el comando falla con No such file or directory. Con find usa siempre -print0 junto con xargs -0; la alternativa es xargs -d '\n', que parte solo por saltos de línea. |
| Esperar que xargs arme un solo comando aunque haya decenas de archivos. | xargs agrupa los nombres que quepan en una línea de comando y repite la ejecución las veces que haga falta. Si quieres exactamente uno por archivo, y no un bloque, agrega -n 1. |
| Meterle xargs rm a la salida de ls y perder el control de lo que borra. | ls no es confiable para eso: no maneja los nombres con espacio ni los saltos de línea, y rm -f no pregunta. Usa find . -name '*.log' -print0 | xargs -0 rm -f y pruébalo primero quitando el rm y poniendo ls. |
Preguntas frecuentes
- ¿Qué hace exactamente xargs?
- Lee texto de la entrada estándar, lo parte en varios argumentos y se los pasa a otro comando. Sirve para encadenar dos comandos: uno produce la lista (ls, find, grep) y el otro la consume. El ejemplo clásico es ls *.txt | xargs wc -l, que cuenta las líneas de todos los .txt de una sola vez.
- ¿Cuál es la diferencia entre xargs y un pipe?
- El pipe (|) pasa la salida de un comando a la entrada del otro, como texto. xargs convierte ese texto en argumentos. Sin xargs, ls *.txt | wc -l contaría las líneas de la lista de nombres; con xargs, wc -l recibe los nombres y cuenta las líneas de cada archivo.
- ¿Por qué se usa xargs -0?
- Porque el separador normal de xargs es el espacio, y hay nombres de archivo que lo traen. El 0 le indica que lea los elementos terminados en byte nulo, que es justo lo que genera find -print0, así que cada nombre llega entero aunque tenga espacios, acentos o saltos de línea.
- ¿Cómo uso un mismo nombre varias veces dentro del comando?
- Con -I seguido del marcador, normalmente {}: find . -name '*.txt' | xargs -I {} cp {} {}.bak crea una copia .bak de cada archivo. Sin -I, el texto {} no se sustituye por nada.
- ¿Qué significa xargs -n 1?
- Que cada ejecución del comando recibe como máximo un elemento de la lista. Es lo más común: sin -n 1, xargs junta los nombres que quepan en una sola llamada y wc -l te da un total en vez de un conteo por archivo. También es lo que necesitas para comandos que solo aceptan un archivo, como mv o gzip.
Ver también
Busca archivos y carpetas por nombre, tipo o tamaño.
31grepBusca texto en archivos o en la salida de otro comando.
35sedBusca y reemplaza texto, o borra líneas, sin abrir el archivo en un editor.
39trCambia, borra o repite caracteres de la entrada.
07lsMuestra los archivos y carpetas que hay en un directorio.