Comandos LinuxExplicados en español
/
Ficha43 / 104
Categoría
Texto
Ejemplos
6
Ver también
find · grep · sed · tr · ls

xargs

eXtended arguments (argumentos extendidos)

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.

Sintaxisxargs [opciones] [COMANDO [argumentos]]
Precaución

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.

§ 1

Despiece

6 ejemplos
Contar líneas de varios archivos

Contar líneas de varios archivos

6 piezas
Lámina01 / 06
Comandols *.txt | xargs wc -l
Piezas6
Escala1:1
N.ºPiezaTipoQué hace
1lsComandoEl primer comando: lista los archivos .txt de la carpeta.
2*.txtArgumentoEl comodín de la terminal: se expande a todos los archivos que terminan en .txt.
3|OperadorEl pipe: manda la salida de ls a la entrada de xargs.
4xargsComandoToma esos nombres y se los pasa como argumentos al comando que sigue.
5wcComandoEl comando que quieres aplicar a cada archivo.
6-lOpciónCuenta líneas en vez de palabras o bytes.
Resultado

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

7 piezas
Lámina02 / 06
Comandols *.txt | xargs -n 1 wc -l
Piezas7
Escala1:1
N.ºPiezaTipoQué hace
1lsComandoLista los archivos .txt de la carpeta.
2*.txtArgumentoEl comodín que se expande a los nombres de los archivos.
3|OperadorPasa la lista a xargs.
4xargsComandoReparte los nombres en varios comandos.
5-n 1OpciónMáximo un elemento por ejecución: el comando corre una vez por archivo.
6wcComandoEl comando que se aplica a cada archivo.
7-lOpciónCuenta líneas.
Resultado

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

9 piezas
Lámina03 / 06
Comandofind . -name '*.jpg' -print0 | xargs -0 ls -1
Piezas9
Escala1:1
N.ºPiezaTipoQué hace
1findComandoBusca archivos por nombre en lugar de listar una sola carpeta.
2.ArgumentoLa carpeta donde empieza la búsqueda: la actual y todo lo que tenga dentro.
3-name '*.jpg'OpciónSolo los archivos cuyo nombre termina en .jpg. Las comillas son para que el asterisco lo vea find y no la terminal.
4-print0OpciónMuestra cada ruta terminada en un byte nulo, un separador que ningún nombre de archivo puede contener.
5|OperadorPasa la lista a xargs.
6xargsComandoReparte los nombres al comando que sigue.
7-0OpciónLee los elementos terminados en byte nulo, para que cada nombre llegue entero.
8lsComandoEl comando que se aplica a cada nombre.
9-1OpciónUn nombre por línea, sin el formato de columnas.
Resultado

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

10 piezas
Lámina04 / 06
Comandofind . -maxdepth 1 -name '*.txt' | xargs -I {} cp {} {}.bak
Piezas10
Escala1:1
N.ºPiezaTipoQué hace
1findComandoBusca los archivos que quieras transformar.
2.ArgumentoLa carpeta donde empieza la búsqueda.
3-maxdepth 1OpciónNo baja a las subcarpetas: solo revisa el primer nivel.
4-name '*.txt'OpciónSolo los .txt.
5|OperadorPasa la lista a xargs.
6xargsComandoVa a correr un cp por cada nombre recibido.
7-I {}OpciónEl texto entre {} es el marcador que se va a sustituir por el nombre de cada archivo.
8cpComandoLa copia.
9{}ArgumentoPrimer marcador: el origen, o sea el archivo encontrado.
10{}.bakArgumentoSegundo marcador: el destino. Al pegarse al nombre, le agrega la extensión .bak.
Resultado

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

9 piezas
Lámina05 / 06
Comandofind . -name '*.log' -print0 | xargs -0 rm -f
Piezas9
Escala1:1
N.ºPiezaTipoQué hace
1findComandoBusca los archivos en todo el árbol de carpetas.
2.ArgumentoLa carpeta actual, de la que cuelgan sus subcarpetas.
3-name '*.log'OpciónSolo los que terminan en .log.
4-print0OpciónSepara los nombres con un byte nulo para que xargs no los parta.
5|OperadorPasa la lista a xargs.
6xargsComandoReparte los nombres al comando que sigue.
7-0OpciónLee los nombres terminados en byte nulo.
8rmComandoEl que borra. Ojo: borra sin preguntar, sin mover a la papelera.
9-fOpciónNo pregunta ni se queja por archivos que ya no existen, que es lo normal cuando rm corre en varios lotes.
Resultado

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

10 piezas
Lámina06 / 06
Comandofind . -name '*.jpg' -print0 | xargs -0 -P 4 -n 1 md5sum
Piezas10
Escala1:1
N.ºPiezaTipoQué hace
1findComandoBusca las imágenes en todo el árbol.
2.ArgumentoLa carpeta actual como punto de partida.
3-name '*.jpg'OpciónSolo los .jpg.
4-print0OpciónSepara los nombres con byte nulo.
5|OperadorPasa la lista a xargs.
6xargsComandoReparte los nombres, ahora en varios comandos al mismo tiempo.
7-0OpciónLee los nombres terminados en byte nulo.
8-P 4OpciónHasta cuatro procesos md5sum corriendo a la vez.
9-n 1OpciónUn archivo por ejecución, para que el trabajo se reparta parejo.
10md5sumComandoCalcula la huella de cada imagen; sirve para compararlas y ver si dos copias son idénticas.
Resultado

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).

§ 2

Opciones

Las que sí vas a usar
OpciónQué hace
-n--max-args=NManda 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.
-0Lee 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--replaceDefine un marcador, normalmente {}, que se sustituye por cada elemento. El comando corre una vez por elemento.
-P--max-procs=NEjecuta hasta N comandos al mismo tiempo. Súbele para tareas lentas como comprimir, convertir imágenes o calcular hashes.
-r--no-run-if-emptyNo 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--verboseMuestra 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=DELIMCambia el separador de la entrada. Útil cuando los datos vienen con comas, como la salida de cut o tr.
-a--arg-file=ARCHIVOLee los argumentos del archivo indicado, uno por línea, en vez de recibirlos por la entrada estándar.
§ 3

Fallas comunes

FallaRemedio
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.
§ 4

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.
§ 5

Ver también