\section{Redirección de entradas y salidas} \label{sec:redireccion} \subsection{Entrada, salida y error estándar} Haremos una breve introducción a los conceptos que definen los componentes de un programa en línea de comandos. Una traducción no oficial de \begin{verbatim} $ info "Text utilities" "Opening the software toolbox" "Toolbox introduction" \end{verbatim} %$ <> La filosofía de Unix (en línea de comandos) cree que un único programa \emph{especializado} para hacer todas las tareas no es bueno, al menos no para usuarios avanzados o administradores. Los usuarios finales sin conocimientos en áreas informáticas pueden preferir tener un sólo programa para todo, pero este único programa tiene dificultades para el mantenimiento y modificación. Se vuelve monstruoso y complicado. En reemplazo se prefiere la \emph{navaja de la Armada Suiza} para tareas cotidianas, o sea, un conjunto de programas pequeños de gran simplicidad que en conjunto se potencian. Para que los programas trabajen en conjunto se utiliza el concepto de \textbf{\emph{flujo}} como una corriente de bytes. Al igual que con las tuberías reales (digamos caños, los grifos o canillas, duchas, etc.) de una casa, se conectan unos a otros donde cada uno tiene una \emph{entrada}, una \emph{función} y una \emph{salida}. El concepto de <> lo veremos en la sección \ref{subsection:tuberias} por ahora vamos a distinguir los otros tres aspectos con un ejemplo. El comando \comando{sort} puede ordenar por orden alfabético. \'{E}sta sería la \emph{función} del programa. Pero ?`qué ordena? bueno aquí es donde interviene la \emph{entrada}. Que sin utilizar la magia de las tuberías, será el \textbf{teclado} la entrada. Haremos una prueba: \begin{verbatim} $ sort El comando sort puede ordenar por orden alfabético \end{verbatim} %$ ... luego presionamos Ctrl-D que significa ``fin de archivo'' en la mayoría de los casos, apareciendo en pantalla: \begin{verbatim} alfabético comando El orden ordenar por puede sort \end{verbatim} Con este ejemplo nos damos cuenta que la \emph{salida} es la \textbf{pantalla} A estas alturas un opodría preguntarse ``Pero no es la única entrada que posee mi programa''; es verdad que un programa puede tener muchas entradas y muchas salidas. Por ejemplo cuando lee un archivo, éste es una entrada más. Pero los conceptos que venimos estudiando son entradas y salidas especiales, llamadas \emph{entrada estándar} y \emph{salida estándar}. También existe un tipo de salida adicional que es el \emph{error estándar}. Por este flujo se canalizan todos los mensajes de error o avisos del programa. Facilitando varias tareas. Una muy común es reunir todos los errores en un archivo separado en caso de problemas, para su posterior análisis. En nuestro ejemplo si \comando{sort} intentaba abrir un archivo y no existía, es preferible que escriba: \begin{verbatim} Fichero o directorio no existe \end{verbatim} Antes de que lo canalice como salida estándar y diga \begin{verbatim} directorio existe Fichero no o \end{verbatim} Teniendo claro los conceptos vamos a ver cómo utilizamos las tuberías para <> los programas entre sí. \subsection{Tuberías (pipes)} \label{subsection:tuberias} Podríamos representar cada programa como una <> que tiene una entrada y una salida que se pueden unir entre ellos. %Debido a que la entrada por defecto es el teclado y la %salida por defecto es terminal, graficaremos cuando sea necesario %ambos. El ejemplo que utilizamos se encuentra esquematizado en la figura \ref{fig:Shell-RedireccionIO-Diagrama-Sort} siendo la entrada estándar el teclado y la salida estándar <> o por simplicidad la pantalla. \figura{Esquema de entrada y salida estándar del ejemplo}{Shell-RedireccionIO-Diagrama-Sort} Vamos a suponer un caso ficticio donde necesitamos todas las definiciones de cada palabra en un texto. Primero las ordenamos alfabéticamente, luego utilizamos un comando ficticio llamado \comando{diccionario} que toma palabras de la entrada estándar y las reescribe junto a su significado en la salida estándar. Su esquema se ve en la figura \ref{fig:Shell-RedireccionIO-Diagrama-Diccionario}. En este caso nombramos por separado las entradas y salidas estándares de los dos programas, pero la <> entre ambos programas se puede considerar como un sólo <>. \figura{Esquema de entrada y salida estándar del ejemplo 2}{Shell-RedireccionIO-Diagrama-Diccionario} En ese tubo, el flujo está en un estado intermedio, donde está ordenado, pero no tiene las definiciones de diccionario. En la línea de comandos esto se escribe de la siguiente manera: \begin{verbatim} $ sort | dicccionario \end{verbatim} %$ Donde el caracter \comando{|} representa la conexión entre la salida estándar de un programa y la entrada estándar de otro. Con este fuerte y simple concepto se pueden concatenar gran cantidad de programas como si fuera una línea de producción en serie para generar resultados complejos. Para mejorar nuestro ejemplo sacaremos las palabras repetidas, antes de mostrarlas con definiciones. Suponiendo que exista un programa llamado \comando{sacar-repetidas}, la línea de comando sería: \begin{verbatim} $ sort | sacar-repetidas | diccionario \end{verbatim} %$ Simple, utilizando herramientas sencillas logramos algo un poco más complicado. El inconveniente que tenemos en este ejemplo es que hay que escribir aquello a procesar. Normalmente queremos utilizar archivos como entrada de nuestros datos. Es necesario un comando que envíe a salida estándar un archivo, así se procesa como la entrada estándar del \comando{sort} y continúa el proceso normalmente. Este comando es \comando{cat}. La sintaxis es simple {\tt cat \emph{nombre-de-archivo}}. Quedando nuestro ejemplo: \begin{verbatim} $ cat archivo.txt | sort | sacar-repetidas | diccionario \end{verbatim} %$ ... crea un glosario de las palabras que se encuentren en \archivo{archivo.txt} La combinación de comandos es incalculable y brinda posibilidades enormes. Veremos algunos ejemplos en los ejercicios. \subsection{Redirección} Si bien nuestro ejemplo es ilustrativo, es bueno ver los resultados en pantalla. En repetidas ocaciones en la vida de un sistema es mejor tener todo en archivos, ya sea para guardar historial de algo o para automatizar ciertas funciones dentro de scripts. Para almacenar o sacar información de archivos y vincularlas con entradas o salidas estándares se utilizan \emph{Redirecciones}. La redirección se expresa con los símbolos <> (>) y <> (<). Se pueden utilizar en forma simple (>) o en forma doble (>>). \subsubsection{Escritura} Para escribir un archivo se utiliza (>). Hay que tener mucho cuidado de no borrar un archivo sobreescribiéndolo. Cuando se utilizan redirecciones, debido a su utilidad en los scripts, \textbf{no se realizan confirmaciones}. Si el archivo a escribir existe y posee información valiosa, aplicar \comando{> archivo-importante} lo sobreescribe con el contenido del flujo. En cambio el operador (>>) realiza un \emph{agregado}\footnote{\emph{append} en inglés} de los datos en el flujo. No hay nada mejor que un ejemplo clarificador: \begin{verbatim} $ escribe-en-salida-estandar > archivo.txt \end{verbatim} %$ El (falso) comando \comando{escribe-en-salida-estándar} justamente hace eso, escribe unas cuantas cosas en salida estándar. Puede ser un \comando{ls}, un \comando{cal} o cualquier comando antes visto, así como también una combinación de comandos por tuberías. En este punto, el contenido de \archivo{archivo.txt} es lo mismo que saldría en pantalla. Si ejecutamos otro comando redireccionado a \archivo{archivo.txt}, éste pierde su contenido y el resultado de la operación pasa a estar en el archivo. Cuando se necesita tener una lista de acontecimientos, no se quiere que un acontecimiento nuevo borre a todos los anteriores. Para lograr esto \emph{agregamos} en vez de sobreescribir. \begin{verbatim} $ echo Este es el acontecimiento Nro. 1 > bitacora.log $ echo Este es el segundo acontecimiento >> bitacora.log \end{verbatim} Va a escribir dos líneas en el archivo \archivo{bitacora.log} sin eliminar nada. \textbf{Ejemplo} Si queremos combinar el ejemplo de las tuberías en la sección \ref{subsection:tuberias} con lo aprendido recientemente podríamos escribir: \begin{verbatim} $ cat archivo.txt | sort | sacar-repetidas | diccionario >> glosario.txt \end{verbatim} %$ \subsubsection{Lectura} Para la lectura es el símbolo inverso (<) y se utiliza de la siguiente manera: \begin{verbatim} $ comando-que-acepta-stdin < archivo-de-entrada.txt \end{verbatim} %$ %% lo afirmado abajo es una mentira piadosa, es solo que no doy %% para entregarlo a tiempo... Debido a que preferimos el comando \comando{cat} para estas operaciones por una mayor legibilidad. %%%%%%%%%%%% % Práctica % %%%%%%%%%%%% \input{Shell/RedireccionIO-practica} .