1. Introducción a los entornos de trabajo UNIX

1.12. Combinación de comandos

Hasta ahora habéis visto numerosos ejemplos de comandos ejecutados individualmente en el terminal. Sin embargo, el intérprete de comandos tiene un gran potencial que permite implementar protocolos de trabajo más sofisticados de manera relativamente sencilla. Un caso paradigmático es la canalización de los resultados de los comandos. En general, la mayoría de los comandos ejecutados en Gnu/Linux generan más información de la que puede aparecer en pantalla físicamente. Por lo tanto, es preferible almacenar los resultados dentro de un archivo para su posterior análisis y visualización. También es posible que nos interese convertir el flujo de datos generado por un proceso emisor de información en la entrada de otro, sin necesidad de generar archivos intermedios. El intérprete de comandos proporciona una serie de funcionalidades para implementar todas estas operaciones relacionadas con la comunicación y el almacenamiento de resultados. En la tabla 10 se muestran las funcionalidades más utilizadas para combinar comandos.

Tabla 10. Combinación de comandos.

Comando Descripción
proceso    >  fichero Redirección de salida
proceso  >>  fichero Redirección de salida sin sobrescribir
proceso  2>  fichero Redirección del canal error
proceso   fichero Redirección de la entrada
proceso 1 |  proceso 2 Comunicación de dos procesos

Fuente: elaboración propia.

El proceso de almacenamiento de datos generados por un proceso en un archivo se conoce como redirección. Un proceso tiene permiso de escritura en dos canales del terminal: salida y error. Los datos generados normalmente por el proceso se transmiten a través del canal de salida, mientras que los errores de ejecución se comunican mediante el canal de error. De manera predeterminada, ambos canales se redirigen a la pantalla (terminal). Si el usuario desea redirigir una de estas dos salidas, debe indicarlo explícitamente al final del comando. El símbolo > indica la redirección del canal de salida, mientras que para redirigir el canal de error se debe usar la construcción 2>. En ambos casos, los datos se almacenan en un archivo que se puede consultar en cualquier momento sin necesidad de volver a ejecutar el comando.

Cada comando tiene asociada una entrada estándar stdin (0) (por defecto, el teclado), una salida estándar stdout (1) (por defecto la consola) y una salida de errores estándar stderr (2) (por defecto también la consola). Por ejemplo, el comando cat, si no recibe argumentos, lee del teclado por la entrada estándar y lo pasa a la salida estándar.

$ cat
Primera secuencia por estudiar

Segunda secuencia por estudiar

^D

El final del stream se lo hemos asignado desde el teclado con la combinación de teclas Ctrl+D.

Se puede cambiar la entrada estándar de cat para que lea de un fichero. También serviría para la mayoría de los comandos: cat, grep, cut, sed…

$ cat < fasta.fa
Name of the system

Nucleotides

…

El operador de redirección de salida > permite cambiar la salida estándar de un comando

$ cal > calendario

Esta orden envía el calendario actual al fichero calendario. En este caso, el stdout del comando cal se redirige a un fichero llamado calendario que contendrá lo que se vería en la pantalla al ejecutar cal.

Para enviar la salida stderr de un programa a un fichero, se ejecuta

$ grep -ioE 'par(en|ro)?t' datos01 2> error.txt.

Para enviar la stdout a la stderr, escribimos en pantalla

$ grep -ioE 'par(en|ro)?t' datos01 1>&2

Y a la inversa, simplemente intercambiando el 1 por 2, se ejecuta

$ grep -ioE 'par(en|ro)?t' datos01 2>&1.

Si se quiere que la ejecución de un comando no genere actividad por pantalla, lo que se denomina ejecución silenciosa, solamente debemos redirigir todas sus salidas a /dev/null. Por ejemplo, pensando en utilizar el comando find (en castellano, buscar), que queremos utilizar para que borre todos los archivos terminados en .mov del sistema:

$ rm -f $(find / -name "*.mov") &> /dev/null

Pero se debe ir con cuidado y estar muy seguro, ya que no tendremos ninguna salida por pantalla.

Los pipes permiten utilizar en forma simple tanto la salida de una orden como la entrada de otra, por ejemplo,

$ ls -l | sed -e "s/[aeio]/u/g"

donde se ejecuta el comando ls y su salida, en vez de imprimirse en la pantalla, se envía (por un tubo o pipe) al programa sed, que imprime su salida correspondiente. Otro ejemplo, para buscar en el fichero /etc/passwd todas las líneas que acaben con la palabra false podríamos hacer

$ cat /etc/passwd | grep false$

donde, primero, se ejecuta el comando cat, y su salida se pasa por grep.  El símbolo $ significa ‘final de la palabra’, por lo que se está identificando con grep todas las líneas que termines con false.

A veces, hay ciertos cambios en la sintaxis de algunos comandos cuando se utilizan las tuberías al transmitir información. Dado que no existen ficheros auxiliares creados a lo largo del pipeline, se debe introducir el carácter «–» para denotar en este caso que la salida del proceso anterior, a través de la tubería, se convierte en el primer argumento de la siguiente ejecución. Para especial atención en la definición del primer archivo a emplear por el comando join.

$ cat fichero1 | sort -k2r | join – fichero2