Tuberías, dobles tuberías, bifurcaciones y múltiples argumentos

Gracias a las pipe (tuberías) podemos en GNU/Linux hacer de fontaneros y hacer que la información salga por un sitio y entre por otro u otros.

Las pipes o tuberías se escriben normalmente con alt gr + 1 y tendríamos que ver “|” (sin las dobles comillas).

por ejemplo con una tubería podemos hacer que la salida de un comando sea la entrada de otro y así poder ir encadenando y procesando información. Veamos un ejemplo sencillote:

$ echo "hola mundo mundial" | wc -w

La salida es 3 en vez de ser “hola mundo mundial”.
¿Qué ha pasado? Pues que la salida de echo ha sido “entubada” gracias a la pipe que hemos colocado a la entrada del comando wc (wc con el argumento -w cuenta las palabras de lo que le venga por la entrada) y este tras procesar nos ha dado como resultado: 3. 3 palabras tiene esa frase.

Veamos otro ejemplo en el que queremos ver los usuarios de un sistema que utilizan la shell fish:

$ grep "/bin/bash" /etc/passwd | wc -l

Eso nos sacará las líneas que contienen “/bin/bash” en el archivo /etc/passwd y se lo pasará a la entrada de wc que con el argumento -l contará las líneas.

Y un tercer ejemplo encadenando varias tuberías:

$ grep "/bin/bash" /etc/passwd | cut -d ":" -f 1 | tr "\n" ";"

En este la salida has de entenderla si te digo que el archivo /etc/passwd tiene valores separados por : de modo que cut -d “:” -f 1 cortará todas las líneas cuando encuentre el primer : de cada línea y eso por tanto nos deja solamente el nombre de los usuarios que coincidan con el filtro “/bin/bash”. Eso tendría que sacar en ese punto x líneas con los nombres de los diferentes usuarios que tienen asignada la shell bash pero como lo entubamos de nuevo va a sustituir tr el retorno de carro por un ; de modo que ya no nos salen 3 o x líneas, nos saldrá un churro con los nombres de los usuarios separados por ;.

Un poco más de tuberías:

$ grep "/bin/bash" /etc/passwd | cut -d ":" -f 1 | tr "\n" ";" | rev | cut -d ";" -f 2-100 | rev

Esta vez con rev le damos la vuelta a la cadena que nos viene con los nombres de usuario separados por ; ya que queremos eliminar el último ; de esa cadena. Eso lo hacemos cortando de nuevo y luego volteando una vez más el resultado.

# Dobles tuberías

Veamos un ejemplo de una doble tubería y que significa esto.

$ ls shit.log || echo "has de crear el archivo shit.log"

ls shit.log tendría que mostrarnos el nombre del archivo shit.log si es que existe en el directorio actual. No existe y por tanto muestra su mensaje pero al meterle una tubería doble tambien ejecutará lo que pongamos tras la tubería. En este caso mostrará el texto “has de crear el archivo shit.log”

Otra opción es que si ls shit.log no obtiene resultado el segundo comando sea touch shit.log , es decir, si no existe el archivo crea el archivo.

La segunda parte de las dobles tuberías solamente se ejecutará si la salida del primer comando es 0.

# Bifurcaciones

  • tee

Con tee podemos por ejemplo guardar una copia de la salida estándar de un comando en un archivo al mismo tiempo que esta se imprime en pantalla. Tee divide la entrada estándar para que se muestre en la salida estándar y en los archivos que necesitemos.

En esta otra captura se puede ver que se usa cat en vez de echo y se usa tee para dejar copia en varios archivos:

 

# Paso de múltiples argumentos a comandos

  • xargs

xargs es de mucha utilidad. Ahora veremos que cosas se pueden hacer.  Con el comando find podemos buscar todos los archivos con extensión .txt del directorio actual. Podemos hacerlo así:

$ find . -name "*.txt"

A esto le podemos sumar que el listado que encuentra find de archivos lo guarde en lista.log tee y siga mostrando la salida de los archivos.

$ find . -name "*.txt" | tee -a lista.log

La opción -a de tee es para que añada de nuevo el listado de archivos en lista.log y no los sobrescriba (aunque sinceramente voy a omitir esto en el siguiente paso para que si sobrescriba. Era solamente por comentarlo)

Y ahora es cuando entra en juego xargs para por ejemplo borrar todos los archivos que tienen extensión .txt del directorio actual. Juntaremos todo para que nos quede un log de los archivos que existían antes de borrarse, es decir, un log de los archivos que han sido borrados.

$ find . -name "*.txt" | tee lista.log | xargs rm

Si hiciésemos un ls ya no existirán los archivos .txt pero si lista.log y en su interior el nombre de los archivos que hemos borrado.

Hemos concatenado find + tee + rm y hemos obtenido una forma de borrar diferentes archivos quedándonos con el informe de los que han sido borrados.

Deja un comentario