miércoles, 10 de marzo de 2010

Programación de la shell

Otro día comentaba ciertas ventajas que proporciona el usar una interfaz de línea de comandos, haciendo hincapié en el arsenal de herramientas disponibles para solucionar todo tipo de problemas, que en caso de usar Linux vienen en su mayoría de fábrica. Pero el verdadero potencial de una shell tradicional frente a una gráfica está relacionado con el hecho de que la primera puede programarse.

Por ejemplo, bash, la shell de GNU incluida en la mayoría de distribuciones Linux, soporta toda una colección de comandos internos que permiten definir y evaluar variables, comprobar condiciones, realizar bucles y, en medio de todo, ejecutar comandos externos o cualquier programa de consola. Esto hace posible el uso de los llamados shell scripts o "guiones de la shell", que no son sino archivos de texto que contienen listas de comandos a ejecutar, pudiendo ir desde una simple secuencia de dos o tres comandos hasta auténticos programas que serán interpretados por la shell para realizar tareas complejas. Además existe la posibilidad (heredada del viejo UNIX) de combinar las numerosas utilidades especializadas de consola con ciertos mecanismos de la shell como el redireccionamiento de E/S y las tuberías, que junto a las estructuras de control mencionadas permiten al usuario construirse sus propios programas para resolver nuevos problemas o automatizar todo tipo de tareas. Un símil válido para describir esta situación: sería como tener una colección de piezas de mecano o módulos básicos ya construidos (los comandos y utilidades de consola) y los tornillos, tuercas y demás mecanismos (proporcionados por la shell) para poder combinarlos y obtener así nuevas máquinas (o piezas) útiles hechas a medida.

Aunque recientemente compartía un shell script para automatizar descargas desde RapidShare que podría servir para ilustrar la idea, incluiré otro más sencillo como ejemplo. Se trata de cambiar puntos por comas en las líneas de temporización de un archivo de subtítulos .SRT (para hacerlo compatible con cierto reproductor de vídeo):

#!/bin/bash
# ^- Indica qué shell debe interpretar el script

archivo="$1"
# ^- Asigna a la variable 'archivo' el primer parámetro
# pasado desde línea de comandos (el archivo .SRT)

numlin=`wc -l $archivo | cut -d' ' -f1`
# ^- Averigua el nº de lineas del archivo combinando
# comandos y lo almacena en variable 'numlin'

echo -e "\nReparando archivo $archivo de $numlin lineas:"
# ^- Mensaje por pantalla indicando lo que va a hacerse

cat /dev/null > rep$archivo
# ^- Creamos un nuevo archivo vacío donde iremos guardando
# los subtitulos reparados en el bucle siguiente

pinta=1
# ^- Inicializamos un contador de lineas

while read linea; do
# ^- Bucle "mientras haya lineas que leer..."

if echo $linea | grep -q ^0[0-9]:
then echo $linea | tr . , >> rep$archivo
# ^- Si la linea actual tiene este aspecto cambiamos
# los puntos por comas
else echo $linea >> rep$archivo
# ^- Si no la guardamos tal y como estaba
fi

pinta=$((contador % 10))
# ^- Calculamos el resto de la división entre 10 del
# nº de lineas

if [ "$pinta" -eq "0" ]
then echo -e ".\c"
fi
# ^- Si el resto es 0 (cada 10 lineas) pintamos un
# punto a modo de barra de progreso

contador=$((contador + 1))
# ^- Incrementamos el contador de lineas

done < $archivo # "... en el archivo de marras" echo -e "\nGenerado archivo rep$archivo\n" # ^- Mensaje final indicando el archivo creado

Típico ejemplo de shell script creado sobre la marcha para resolver un problema específico; en este caso había que automatizar la conversión de ciertos caracteres en ciertas líneas de un archivo de texto. Por supuesto, en Internet tenemos montones de shell scripts listos para usar o para examinar y aprender como hacer los nuestros. Y en nuestro propio sistema Linux podemos obtener una lista de shell scripts instalados ejecutando desde consola la siguiente línea:

IFS=':';for dir in $PATH;do file $dir/*|grep shell;done

Por último el material de referencia imprescindible para aprender a sacar partido de bash:
Ahora solo es cuestión de ponerse manos a la obra cuando se nos presente (o se nos ocurra) algún problema informático. Próximamente compartiré el penúltimo shell script que he escrito para salvar y restaurar metadatos de los archivos de audio.