Cómo usar el comando xargs en Linux

¿Necesita encadenar algunos comandos de Linux, pero uno de ellos no acepta entrada canalizada? xargs puede tomar la salida de un comando y enviarla a otro comando como parámetros.

Todas las utilidades estándar de Linux tienen tres flujos de datos asociado con ellos. Son el flujo de entrada estándar (stdin), el flujo de salida estándar (stdout) y el flujo de error estándar (stderr).

Estos flujos funcionan con texto. Enviamos la entrada (stdin) a un comando usando texto, y la respuesta (stdout) se escribe en la ventana de terminal como texto. Los mensajes de error también se escriben en la ventana del terminal como texto (stderr).

Una de las grandes características de los sistemas operativos Linux y tipo Unix es la capacidad de canalizar la salida stdout de un comando a la entrada stdin de un segundo comando. Al primer comando no le importa que su salida no vaya a una ventana de terminal, y al segundo comando no le importa que su entrada no provenga de un teclado.

Aunque todos los comandos de Linux tienen los tres flujos estándar, no todos aceptan la salida estándar de otro comando como entrada a su stdin. Eso significa que no puede canalizar la entrada a ellos.

xargs es un comando para construir canalizaciones de ejecución utilizando los flujos de datos estándar. Al usar xargs podemos hacer que comandos como echo, rm y mkdir acepten entradas estándar como argumentos.

El comando xargs

xargs aceptará entrada canalizada. También puede aceptar la entrada de un archivo. xargs usa esa entrada como parámetros para los comandos con los que le hemos dicho que trabaje. Si no le decimos a xargs que trabaje con un comando específico, por defecto usará echo.

Podemos usar eso para demostrar cómo xargs siempre generará una sola línea de salida, incluso a partir de una entrada de varias líneas.

Si usamos la opción -1 (enumerar un archivo por línea) con ls, obtenemos un columna única de nombres de archivo.

ls -1 ./*.sh

v en una ventana de terminal

Esto enumera los archivos de script de shell en el directorio actual.

salida de ls en una ventana de terminal

Obtenemos una sola columna como se esperaba. Si lo canalizamos a través de xargs, ¿qué obtenemos?

ls -1 ./*.sh | xargs

ls -1 ./*.sh |  xargs en una ventana de terminal

La salida se escribe en la ventana de la terminal, como un largo flujo de texto.

  Cómo configurar IntelliJ IDEA IDE en Linux

Se canaliza a través de xargs en una ventana de terminal

Es esta capacidad la que permite a los xargs introducir parámetros en otros comandos.

Usar xargs con wc

Podemos usar xargs para que podamos contar fácilmente palabras, caracteres y líneas en varios archivos.

ls *.page | xargs wc

ls * .page |  xargs wc en una ventana de terminal

Esto es lo que pasa:

ls enumera los archivos * .page y pasa la lista a xargs.
xargs pasa los nombres de archivo a wc.
wc trata los nombres de archivo como si los hubiera recibido como parámetros de línea de comando.

salida de wc en una ventana de terminal

Las estadísticas de cada archivo se muestran junto con un total general.

Uso de xargs con confirmación

Podemos usar la opción -p (interactiva) para que xargs nos pida confirmación de que estamos felices de que continúe.

Si pasamos una cadena de nombres de archivo a tocar, a través de xargs, se tocará crea los archivos para nosotros.

echo 'one two three' | xargs -p touch

echo 'uno dos tres' |  xargs -p touch en una ventana de terminal

Se muestra el comando que se va a ejecutar y xargs espera a que respondamos escribiendo “y” o “Y”, o “n” o “N”, y presionando Enter.

Si solo presiona Enter, se trata como «n». El comando solo se ejecuta si escribe “y” o “Y”.

xargs solicitando confirmación en una ventana de terminal

Presionamos “y” y presionamos Enter. Podemos usar ls para comprobar que se han creado los archivos.

ls one two three

salida de ls en una ventana de terminal

Uso de xargs con varios comandos

Podemos usar múltiples comandos con xargs usando la opción -I (argumentos iniciales).

Esta opción define una «cadena de reemplazo». Dondequiera que aparezca el token para la cadena de reemplazo en la línea de comando, se insertan los valores que se proporcionaron a xargs.

Usemos el comando de árbol para mirar los subdirectorios del directorio actual. La opción -d (directorio) hace que el árbol ignore los archivos y solo informe sobre los directorios.

tree -d

árbol -d en una ventana de terminal

Hay un solo subdirectorio llamado «imágenes».

En un archivo llamado “directorios.txt”, tenemos los nombres de algunos directorios que deseamos haber creado. Podemos mirar su contenido usando cat.

cat directories.txt

cat directorios.txt en una ventana de terminal

Usaremos esto como datos de entrada para xargs. El comando al que vamos es este:

cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'

Esto se descompone así:

cat directorios.txt |: Esto inserta el contenido del archivo directrories.txt (todos los nuevos nombres de directorio) en xargs.
xargs -I%: Esto define una «cadena de reemplazo» con el token «%».
sh -c: Esto inicia una nueva subcapa. El -c (comando) le dice al shell que lea los comandos de la línea de comandos.
‘eco %; mkdir% ‘: cada uno de los tokens “%” será reemplazado por los nombres de directorio que son pasados ​​por xargs. El comando echo imprimirá el nombre del directorio; el comando mkdir creará el directorio.

  Cómo utilizar NitroShare en Linux

cat directorios.txt |  xargs -I% sh -c 'echo%;  mkdir% 'en una ventana de terminal

Los directorios se enumeran uno por uno.

salida de xargs en una ventana de terminal

Podemos usar tree una vez más para verificar que se hayan creado los directorios.

tree -d

salida del árbol en una ventana de terminal

Copiar archivos en varias ubicaciones

Podemos usar xargs para permitirnos copiar archivos a múltiples ubicaciones con un solo comando.

Vamos a canalizar los nombres de dos directorios en xargs como parámetros de entrada. Le diremos a xargs que solo pase uno de estos parámetros a la vez al comando con el que está trabajando.

En este caso, el comando es cp. Entonces, el efecto es llamar a cp dos veces, cada vez con uno de los dos directorios como parámetro de línea de comandos. El parámetro xargs que permite que esto suceda es la opción -n (número máximo). Vamos a configurar esto para que sea uno.

También estamos usando la opción -v (detallado) con cp para que informe lo que está sucediendo.

echo ~/Backups/ ~/Documents/page-files/ | xargs -n 1 cp -v ./*.page

echo ~ / Backups / ~ / Documents / page-files / |  xargs -n 1 cp -v ./*.page en una ventana de terminal

Los archivos se copian en los dos directorios, un directorio a la vez. cp informa cada acción de copia de archivo para que podamos verlas.

salida de xargs y cp en una ventana de terminal

Eliminar archivos en directorios anidados

Si los nombres de archivo tienen espacios y caracteres extraños, como caracteres de nueva línea, xargs no podrá interpretarlos correctamente. Podemos superar ese problema utilizando la opción -0 (terminador nulo). Esto le dice a xargs que use el carácter nulo como delimitador final para los nombres de archivo.

Usaremos find en este ejemplo. Find tiene su propia opción para tratando con espacios en blanco y caracteres extraños en los nombres de archivo. Es la opción -print0 (nombre completo, carácter nulo).

find . -name "*.png" -type f -print0 | xargs -0 rm -v -rf "{}"

Esto se descompone así:

encontrar . -name “* .png”: find va a buscar desde el directorio actual “.” para objetos con nombres que coincidan con «* .png» que sean archivos (tipo -f).
-print0: los nombres terminarán con un carácter nulo y se atenderán los espacios y caracteres extraños.
xargs -0: xargs también considerará que los nombres de archivo terminan en nulo, y los espacios y caracteres extraños no causarán problemas.
rm -v -rf “{}”: rm será detallado e informará lo que está sucediendo (-v). Será recursivo (-r) y buscará a través de subdirectorios anidados, y eliminará archivos sin preguntar (-f). El «{}» se reemplaza por cada nombre de archivo.

encontrar .  -nombre

Se buscan todos los subdirectorios y se eliminan los archivos que coinciden con el patrón de búsqueda.

  Cómo alojar una alternativa personal de Pastebin en Linux

Salida de rm en una ventana de terminal

Eliminación de directorios anidados

Digamos que queremos eliminar un conjunto de subdirectorios anidados. árbol nos dejará verlos.

tree -d

árbol -d en una ventana de terminal

find . -name "level_one" -type d printo | xargs -o rm -v -rf "{}"

Este comando usará find para buscar de forma recursiva dentro del directorio actual. El objetivo de la búsqueda es un directorio llamado «level_one». Los nombres de directorio se pasan a través de xargs a rm.

encontrar .  -nombre

Los únicos cambios significativos entre este comando y el comando anterior son que el término de búsqueda es el nombre del directorio superior y el tipo d le dice a find que busque directorios, no archivos.

salida de find y xargs y rm en una ventana de terminal

El nombre de cada directorio se imprime a medida que se elimina. Podemos comprobar con el árbol:

tree -d

árbol -d en una ventana de terminal

Se eliminan todos los subdirectorios anidados.

Eliminar todos los archivos, excepto un tipo de archivo

Podemos usar find, xargs y rm para eliminar todos los archivos excepto un tipo que queremos retener. Es un poco contradictorio, pero proporcionamos el nombre del tipo de archivo que deseamos conservar, no el nombre de los que deseamos eliminar.

La opción -not le dice a find que devuelva los nombres de los archivos que no coinciden con el patrón de búsqueda. Estamos usando la opción -I (argumentos iniciales) con xargs una vez más. Esta vez, el token de cadena de reemplazo que estamos definiendo es «{}». Esto se comportará exactamente igual que el token de cadena de reemplazo que generamos anteriormente, que resultó ser un «%».

find . -type f -not - name "*.sh" -print0 | xargs -0 -I {} rm -v {}

encontrar .  -tipo f -no - nombre

Podemos comprobar con ls. Los únicos archivos que quedan en el directorio son los que coinciden con el patrón de búsqueda «* .sh».

ls -l

salida de ls en una ventana de terminal

Creación de un archivo de almacenamiento con Xargs

Podemos usar find para buscar archivos y pasarlos a través de xargs a tar, para crear un archivo de almacenamiento.

Vamos a buscar en el directorio actual. El patrón de búsqueda es «* .page», por lo que buscaremos archivos «.page».

find ./ - name "*.page" -type f -print0 | xargs -0 -tar -cvzf page_files.tar.gz

buscar ./ ​​- nombre

Los archivos se enumeran como se esperaba, a medida que se crea el archivo de almacenamiento.

salida de alquitrán en una ventana de terminal

El mediador de datos

A veces necesitas un pequeño andamio cuando apilas cosas juntas. xargs cierra la brecha entre los comandos que pueden enviar información y los comandos que no están diseñados para recibirla.

Tanto xargs como find tienen una gran cantidad de opciones. Le recomendamos que consulte sus páginas de manual para obtener más información.