La guía definitiva para entender las tuberías y redireccionamientos en Linux

Introducción

En los dos artículos anteriores vimos una colección de filtros que manipularían datos para nosotros. En este artículo veremos cómo podemos unirlos para hacer una manipulación de datos más poderosa.

Hay un poco de lectura involucrada en esta sección. Aunque los mecanismos y su uso son bastante simples, es importante comprender varias características sobre su comportamiento si deseas utilizarlos de manera efectiva.

¿Qué son?

Cada programa que ejecutamos en la línea de comandos tiene automáticamente tres flujos de datos conectados.

  • STDIN (0): entrada estándar (datos introducidos en el programa)
  • STDOUT (1): Salida estándar (datos impresos por el programa, por defecto en la terminal)
  • STDERR (2): Error estándar (para mensajes de error, también predeterminados para la terminal)

Las tuberías y la redirección son los medios por los cuales podemos conectar estos flujos entre programas y archivos para administrar los datos de manera interesante y útil.

Demostraremos las tuberías y la redirección a continuación con varios ejemplos, pero estos mecanismos funcionarán con cada programa en la línea de comandos, no solo los que hemos usado en los ejemplos.

Redireccionando a un archivo

Normalmente, obtendremos nuestro resultado en la pantalla, lo cual es conveniente la mayor parte del tiempo, pero a veces podemos desear guardarlo en un archivo para guardarlo como un registro, usarlo en otro sistema o enviarlo a otra persona.

El operador mayor que (>) indica a la línea de comandos que deseamos que la salida del programa (o lo que sea que envíes a STDOUT) se guarde en un archivo en lugar de imprimirse en la pantalla. Veamos un ejemplo.

Vamos a desglosarlo:

  • Línea 1 Comencemos por ver qué hay en nuestro directorio actual.
  • Línea 3 Ahora ejecutaremos el mismo comando, pero esta vez usamos > para indicarle a la terminal que guarde la salida en el archivo myoutput. Notarás que no necesitamos crear el archivo antes de guardarlo. La terminal lo creará automáticamente si no existe.
  • Línea 4 Como puedes ver, nuestro nuevo archivo ha sido creado.
  • Línea 6 Echemos un vistazo a lo que se guardó allí.

Algunas observaciones

Notarás que, en el ejemplo anterior, la salida guardada en el archivo era un archivo por línea en lugar de toda una línea cuando se imprime en la pantalla. La razón de esto es que la pantalla tiene un ancho conocido y el programa puede formatear su salida para adaptarse a eso.

Cuando estamos redirigiendo, puede ser a un archivo, o podría estar en otro lugar, por lo que la opción más segura es formatearlo como una entrada por línea. Esto también nos permite manipular más fácilmente esos datos más adelante, ya que lo veremos más adelante en la página.

Truco

Al redirigir y usar tuberías, los datos reales siempre serán los mismos, pero el formato de esos datos puede ser ligeramente diferente al que normalmente se imprime en la pantalla. Mantén esto en mente.

También notarás que el archivo que creamos para guardar los datos también está en nuestra lista. La forma en que funciona el mecanismo, el archivo se crea primero (si aún no existe) y luego el programa se ejecuta y la salida se guarda en el archivo.

Guardar en un archivo existente

Si redirigimos a un archivo que no existe, se creará automáticamente para nosotros. Sin embargo, si guardamos en un archivo que ya existe, se borrará su contenido y se guardará la nueva salida.

En su lugar, podemos obtener los datos nuevos que se agregarán al archivo utilizando el operador doble mayor que (>>).

Redirigir desde un archivo

Si usamos el operador menor que (<), entonces podemos enviar datos de la otra manera. Leeremos los datos del archivo y los alimentaremos al programa a través de su flujo STDIN.

Muchos programas (como hemos visto en secciones anteriores) nos permiten proporcionar un archivo como argumento de línea de comandos y leerá y procesará el contenido de ese archivo. Dado esto, es posible que te preguntes por qué necesitaríamos usar este operador. El ejemplo anterior ilustra una diferencia sutil pero útil.

Notarás que cuando ejecutamos wc suministrando el archivo para procesar como argumento de línea de comandos, la salida del programa incluía el nombre del archivo que fue procesado. Cuando lo ejecutamos redirigiendo el contenido del archivo a wc, el nombre del archivo no se imprimió.

Esto se debe a que cada vez que usamos redirección o tuberías, los datos se envían de forma anónima. Entonces, en el ejemplo anterior, wc recibió algo de contenido para procesar, pero no tiene conocimiento de dónde vino, por lo que es posible que no imprima esta información. Como resultado, este mecanismo a menudo se usa para obtener datos auxiliares (que pueden no ser necesarios) para que no se impriman.

Podemos combinar fácilmente las dos formas de redireccionamiento que hemos visto hasta ahora en un solo comando, como se ve en el siguiente ejemplo.

Redireccionando STDERR

Ahora veamos la tercera secuencia que es Error estándar o STDERR. Los tres flujos en realidad tienen números asociados (entre paréntesis en la lista en la parte superior de la página). STDERR es la secuencia número 2 y podemos usar estos números para identificar las secuencias.

Si colocamos un número antes del operador >, redirigirá esa secuencia (si no usamos un número, como lo hemos estado haciendo hasta ahora, el valor predeterminado es la secuencia 1).

Tal vez deseamos guardar tanto la salida normal como los mensajes de error en un solo archivo. Esto se puede hacer redirigiendo la secuencia STDERR a la secuencia STDOUT y redirigiendo STDOUT a un archivo.

Redirigimos a un archivo primero y luego redirigimos el flujo de error. Identificamos la redirección a una secuencia colocando un & delante del número de secuencia (de lo contrario, redirigiría a un archivo llamado 1).

Tuberías

Hasta ahora hemos tratado de enviar datos hacia y desde archivos. Ahora veremos un mecanismo para enviar datos de un programa a otro. Se llama tubería y el operador que utilizamos es (|) (se encuentra arriba de la tecla de barra invertida (\) en la mayoría de los teclados).

Lo que este operador hace es alimentar la salida del programa a la izquierda como entrada al programa a la derecha. En el siguiente ejemplo, enumeraremos solo los primeros 3 archivos en el directorio.

Podemos usar tuberías en tantos programas juntos como queramos. En el siguiente ejemplo, hemos usado tuberías en la salida a la cola para obtener solo el tercer archivo.

Truco

Cualquier argumento de línea de comandos que proporcionemos para un programa debe estar al lado de ese programa.

Truco

A menudo encuentro que las personas intentan y escriben sus tuberías de una vez y cometen un error en algún lugar a lo largo de la línea. Luego piensan que está en un punto, pero de hecho es otro punto.

Pierden mucho tiempo tratando de solucionar un problema que no está allí mientras no ven el problema que está allí. Si construyes tus tuberías gradualmente, no caerás en esta trampa. Ejecuta el primer programa y asegúrate de que proporcione el resultado que esperabas. Luego agrega el segundo programa y verifica nuevamente antes de agregar el tercero y así sucesivamente. Esto te ahorrará mucha frustración.

También puedes combinar tuberías y redireccionamiento.

Más ejemplos

A continuación, te presento algunos ejemplos más para dar una idea del tipo de cosas que puedes hacer con las tuberías. Hay muchas cosas que puedes lograr con las tuberías y estas son solo algunas de ellas.

Con experiencia y un poco de pensamiento creativo, estoy seguro de que encontrarás muchas más formas de utilizar las tuberías para facilitarle la vida.

Todos los programas utilizados en los ejemplos son programas que hemos visto antes. Sin embargo, he utilizado algunos argumentos de línea de comandos que aún no hemos cubierto.

Busca las páginas de manual relevantes para averiguar qué hacen. También puedes probar los comandos tú mismo, aumentando gradualmente para ver exactamente qué está haciendo cada paso.

En este ejemplo, estamos ordenando la lista de un directorio para que todos los directorios aparezcan primero.

En este ejemplo alimentaremos menos la salida de un programa en el programa para que podamos verlo más fácilmente.

Identifiquemos todos los archivos en tu directorio de inicio para los cuales el grupo tiene permiso de escritura.

Crear una lista de cada usuario que posee un archivo en un directorio dado, así como cuántos archivos y directorios posee.

Resumen

Lo que aprendimos

Guardar salida en un archivo.

>> 

Agregar salida a un archivo.

Leer la entrada de un archivo.

2>

Redirigir mensajes de error.

|

Envía la salida de un programa como entrada a otro programa.

Conceptos importantes

Flujos

Cada programa que puedes ejecutar en la línea de comando tiene 3 secuencias, STDIN, STDOUT y STDERR.

Practicando lo aprendido

Analicemos algunos datos:

  • En primer lugar, experimenta guardando la salida de varios comandos en un archivo. Sobrescribe el archivo y añádelo también. Asegúrate de utilizar rutas absolutas y relativas a medida que avanzas.
  • Ahora observa si puedes incluir solo el vigésimo último archivo en el directorio /etc.
  • Finalmente, observa si puedes obtener un recuento de cuántos archivos y directorios tienen permisos de ejecución en tu directorio de inicio.