Entradas y salidas estandar de Bash

La base de la programación de scripts en Bash son los descriptores de ficheros, es decir, stdin y stdout. Estos son básicamente los dos medios que utilizamos para comunicarnos con una aplicación en Bash: stdin escucha y stdout habla, así de sencillo.
Por lo tanto, cuando un programa está siendo ejecutado y utiliza una función del tipo echo, print o println, lo que sea que vaya a escribir, lo hará a stdout.
El uso más común y quizás el más útil de estos descriptores, es el llamado "piping": enviar la salida (stdout) de un programa como entrada (stdin) para otro.
El ejemplo más sencillo es utilizar "ls" para mostrar el contenido de un directorio, el cual, dada la gran cantidad de ficheros, nos es imposible de contener dentro de una pantalla de consola. Utilizando otra utilidad como "less" o "more" podemos realizar una pausa entre cada salto de pantalla para verificar los ficheros. Algo así como el dir /p de DOS:

$ ls -l

Devuelve una lista demasiado larga para que podamos verla. Por esto vamos a utilizar el "piping" para dirigir la salida (stdout) de ls -l hacia la entrada (stdin) de more:

$ ls -l | more

Nada complicado hasta ahora. El símbolo "|" (AltGr+1) es el que hace toda la magia. Existen otros dos símbolos mágicos: > y <. Vamos a dar un ejemplo de cada uno y su uso más común. El más sencillo de comprender es > el cual envía la stdout a alguna parte, en este caso, a un fichero.

$ls -la > foo.txt

Si el fichero no existe, es creado y rellenado con la salida (stdout) de "ls -la". Si el fichero existe (muy importante!) todos los datos son reemplazados, así que cuidadin. Además de > podemos utilizar >> lo cual escribe la salida al final del fichero. Por ejemplo, supongamos que foo.txt no existe:

$dmesg >> foo.txt
$cat /var/log/syslog >> foo.txt

Entonces, foo.txt contiene la información de dmesg y el último syslog.

El más complicado puede que sea <. Básicamente lo utilizamos para inyectar algo en el programa que vamos a ejecutar. Supongamos que tenemos una serie de comandos para MySQL en un fichero foo.mysql y queremos ejecutarlos desde la línea de comandos:

$mysql -u root -p < foo.mysql

Hará el truco.
Finalmente, los "File Descriptors" son sólo un nombre chulo que darles a stdin (File descriptor 0) y stdout (File descriptor 1).