5.7.- Gestionando las entradas/salidas de un script

Redirección de entradas/salidas estándar

El comando interno exec permite manipular los descriptores de archivo del shell en ejecución. Si se usa en el interior de un script, permite la redirección de manera global de las entradas/salidas del mismo.

Redirigir la entrada estándar de un script

Los comandos del script situados después de esta directiva y que leen de su entrada estándar, extraerán sus datos desde archivo1. Por lo tanto no habrá más interacción con el teclado.

Redirigir la salida estándar y la salida de error estándar de un script

Los comandos del script situados después de esta directiva y que describen en su salida estándar, enviarán sus resultados a archivo1. Los que escriban en su salida de error estándar enviarán sus errores a archivo2.

Redirigir la salida estándar y la salida de error estándar de un script al mismo archivo

Todos los comandos del script situados después de esta directiva enviarán sus resultados y sus errores a archivo1 (ver sección Redirecciones).

Ejemplo 1

Después de ejecutarlo vamos a listar los archivos resultantes resumen y log:

Viendo los resultados, no es práctico tener los mensajes de resultado y los mensajes de error en archivos distintos ya que sería difícil reconstruir la cronología de los eventos.

Ejemplo 2

El script batch2 envía su salida estándar y su salida de error estándar  ~/bash/log (es mi directorio de trabajo actual):

Ejecutamos el script y comprobamos el contenido del archivo log:

El archivo ~/bash/log agrupa todas las impresiones y refleja el orden cronológico de los eventos ocurridos.

Ejemplo 3

Veamos un ejemplo para un archivo de datos que llamaremos agenda.txt y que será leído por el script lectura:

archivo agenda.txt (sólo es un ejemplo representativo, puedes variar los datos):

Después de haber creado una mini agenda seguimos con el script que leerá el archivo agenda.txt:

Ejecutamos el script:

  • Crea tu propia agenda o diario con lo aprendido.

Gestión de archivos

Los shell actuales ofrecen funcionalidades adicionales a las descritas anteriormente. Nos permite abrir y manipular los archivos usando descriptores comprendidos entre 3 y 8 (además de 0, 1, 2). La ventaja es que podemos manipular los archivos conservando los descriptores 0, 1 y 2 conectados al terminal.

Apertura de archivo

Para lectura:

Para escritura:

Lectura de un archivo

Sintaxis:

Escritura en un archivo

Cierre de un archivo

Después de estos datos veamos un ejemplo de un script que llamaremos lectura2 que leerá las dos primeras líneas del archivo agenda.txt, y las mostrará por pantalla escribiéndolas en el archivo out.txt.

Este listado al ejecutarlo nos mostrará por pantalla las dos primeras líneas…

… pero, también ha escrito el resultado en un archivo llamado out.txt.

Tratamiento de un archivo

Información previa

Recordando las características de read

Para leer una línea de un archivo se realiza con el comando read. Veamos un recordatorio de las características de este comando:

  • Lee una línea del descriptor 0 (entrada estándar).
  • Devuelve un código verdadero si ha leído una línea (incluso si está vacía).
  • Devuelve el código false cuando encuentra el final de un archivo.

Visto estos puntos, tenemos que, para leer todas las líneas de un archivo la realizamos asociando el comando read y el bucle while.

Concepto de final de archivo

Cuando la entrada estándar (descriptor 0) de read está conectada al terminal (por defecto), el concepto de final de archivo tiene que ser enviado por el usuario mediante las teclas ctrl-d.

Si la entrada estándar del comando está conectada a un archivo regular, el núcleo de Unix/Linux previene a read cuando se llega al final del archivo. Para el desarrollador, solamente el test del código de retorno de read indica que el comando ha llegado al final del archivo.

Diferentes formas de explotar un archivo

Redirigir la ejecución del script

Veamos las redirecciones que podemos realizar en el momento de ejecutar el script.

Ejemplo:

Este script al que llamaremos leearchivo1 usa los comandos read y print y no realiza ninguna redirección. El archivo de entrada es el teclado y el archivo de salida es el terminal:

Terminal Korn shell 

Ejecutando el script

Ahora un listado con el terminal bash

Vemos el resultado de la ejecución:

LA entrada y salida estándar del shell (lo que el script interpreta) se asocian respectivamente a los archivo agenda.txt y salida.txt antes de que el script leearchivo1 comience a ejecutarse. Todos los comandos del script que leen de su entrada estándar (en este caso read)  sacan sus datos del archivo agenda.txt (creado anteriormente) todos los que escriben en su salida estándar (en este caso print) envían sus impresiones al archivo salida.txt.

Versión para Bourne Shell

Resultando:

 Redirección de un bloque

Podemos redirigir únicamente los comandos situados en el interior de una estructura de control o bloque. Las redirecciones tienen que escribirse detrás de la palabra clave que cierra la estructura de control.

Ejemplo

Cuando lo ejecutamos obtenemos el resultado del archivo salida.txt con el comando nl:

En este script, las redirecciones solo conciernen a los comandos internos al bucle while.

Redirigir un bloque a los archivos abiertos

Nos mostrará la ejecución siguiente:

Repartir una línea de campos

Si tenemos las líneas del archivo estructuradas en campos, es muy fácil recuperar cada campo en una variable. Para ello, tenemos que modificar el valor de la variable IFS (repasa la sección; El comando read).

Ejemplo

Este script que llamaremos  leearchivo6 genera a partir del archivo agenda.txt, una salida por pantalla que coge el formato del archivo tratado, pero añadiendo “(+0)” delante de los teléfonos de los clientes localizados en la península y Baleares, y “(-1)” para los clientes localizados en las Islas Canarias. La variable IFS se inicializa con el valor del carácter que hace de separador de campos del archivo agenda.txt (en este caso|“).

El comando read recibe cinco nombres de variables como argumento…

… por lo tanto reparte la línea leída en campos usando el carácter “|“.

Por lo tanto la línea se divide automáticamente. Sólo nos queda comprobar el valor del código postal y volver a unir la línea insertando la diferencia de horario.

Ejecutando el script:

  • Con lo aprendido, crea una base de datos de una tienda de mascotas.