En el mundo de la interfaz de línea de comandos, los programas suelen interactuar con tres flujos de datos estándar:
stdin): de dónde recibe un programa su entrada (normalmente del teclado).stdout): a dónde envía un programa su salida normal (normalmente a la pantalla de la terminal).stderr): a dónde envía un programa sus mensajes de error (normalmente a la pantalla de la terminal).Recuerda que presentamos estos tres flujos en el capítulo Pipelines y listas de comandos.
Un pipeline se puede considerar una forma de redirección: la salida estándar de un programa se envía directamente a la entrada estándar de otro. Ya vimos los pipelines. En este concepto veremos cómo redirigir desde archivos y hacia archivos.
La redirección del shell es un mecanismo poderoso que te permite cambiar el destino de estos flujos. En lugar de que un programa lea del teclado o escriba en la pantalla, puedes redirigir la entrada desde un archivo o enviar la salida a un archivo. Esto te da bastante flexibilidad y control sobre cómo los programas interactúan con los datos.
Estos son los operadores de redirección más comunes y lo que hacen:
> (redirección de salida)Propósito: redirigir la salida estándar (stdout) de un comando a un archivo.
Comportamiento:
Ejemplo:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
La redirección se hace antes de que se ejecute el comando. Esto significa que no puedes redirigir hacia el mismo archivo del que necesitas leer.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
En el segundo comando del ejemplo anterior,
>> (redirección de salida con adición)Propósito: agregar la salida estándar (stdout) de un comando al final de un archivo.
Comportamiento:
Ejemplo:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (redirección de entrada)Propósito: redirigir la entrada estándar (stdin) de un comando desde un archivo.
Comportamiento: el comando lee su entrada del archivo indicado en lugar del teclado.
Ejemplo:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (redirección de errores):stderr) de un comando a un archivo.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Puedes agregar el error estándar a un archivo con 2>>.
También hay redirecciones que pueden combinar stdin y stderr.
Consulta el manual para más detalles.
/dev/null/dev/null es un archivo especial que
A veces se le llama «el bitbucket». Es útil para suprimir la salida o los errores.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Puedes dar varias redirecciones a la vez.
some_command < input.txt > output.txt 2> error.txt
Una redirección se puede copiar.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Cuando veas 2>&1, léelo como «redirige el error estándar a lo que sea a lo que la salida estándar esté apuntando en ese momento».
Bash procesa las instrucciones de redirección estrictamente de izquierda a derecha, lo que significa que puedes hacer esto:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
En el contexto de la programación del shell y de sistemas operativos como Linux/Unix, un descriptor de archivo (FD) es un número entero no negativo que sirve como identificador o referencia de un archivo abierto o de un recurso de E/S (entrada/salida). Piénsalo como una etiqueta o un número de referencia que el sistema operativo usa para llevar la cuenta de los archivos abiertos y los flujos de datos.
Los números que ves a la izquierda de las redirecciones son descriptores de archivo.
A los flujos de E/S estándar se les asignan los 3 primeros descriptores de archivo:
Puedes establecer o crear nuevos descriptores de archivo con el comando exec y los operadores de redirección.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Esta técnica parece bastante enrevesada, pero puede ser muy útil cuando tu script lo ejecuta otro paquete de software y ese software captura automáticamente la salida estándar.
El comando bats, que se usa para ejecutar las pruebas unitarias de este track, funciona así: bats captura el stdout y el stderr de una prueba, pero los mensajes de depuración enviados al FD 3 se muestran en la terminal.
¿Por qué es útil la redirección?
Las redirecciones del shell te dan un control detallado sobre cómo los programas interactúan con los datos, y te permiten construir flujos de trabajo complejos y gestionar la información de forma eficaz.