lunes, 31 de marzo de 2014

Trucos de la línea de comandos de Linux

Aprovechando el reencuentro con commandlinefu.com, una web muy interesante que descubrí hará un par de años pero había olvidado, voy a empezar una serie de posts dedicada a recoger ciertos trucos sencillos pero muy potentes que podemos usar en la línea de comandos de Linux. Algunos estarán relacionados con funcionalidades de la propia shell Bash y otros con la utilidad proporcionada por ciertos comandos y programas habituales en estos sistemas operativos.

Ahí van los 5 primeros, relacionados con la terminal de comandos y la gestión del directorio de trabajo (working directory) o directorio actual:
  • Limpiar la terminal de comandos: en lugar de teclear el comando clear y pulsar Enter, pulsar directamente la combinación de teclas Ctrl+L.
  • Cerrar la shell actual: en lugar de teclear el comando exit o logout y pulsar Enter, podemos pulsar directamente Ctrl+D, que finaliza la entrada de datos en general y en este caso particular la entrada de comandos a la shell.
  • Volver a nuestro directorio personal: la forma más corta es ejecutando el comando interno cd sin pasarle ningún argumento (y pulsando Enter, claro).
  • Volver al directorio anterior: cuando estamos moviéndonos por el arbol de directorios, para regresar al directorio anterior sin tener que especificar su nombre/ubicación al usar cd, lo más cómodo es ejecutar cd -.
  • Restablecer la terminal de comandos: si por desgracia acabamos con una terminal de comandos que muestra caracteres extraños, por ejemplo tras volcar a pantalla el contenido de un archivo binario con cat, podemos restablecer su configuración con el comando reset.
En la próxima entrega me centraré en trucos relacionados con el historial de comandos anteriormente ejecutados en la shell, lo que puede ahorrar al usuario bastantes pulsaciones de teclas (y minutos) a lo largo del día...

martes, 25 de marzo de 2014

El tiempo de la AEMET en la consola

Hace tiempo que publiqué en este blog un script para tener en la consola de comandos el parte meteorológico. Por desgracia, ese tipo de scripts funcionan mientras no cambie el tipo y el formato de la información "rascada" de la web correspondiente, y cada vez quedan menos que proporcionen información textual, sin iconos ni gráficos.

Cuando el script de marras dejó de funcionar, lo primero fue buscar un sitio web menos "voluble" que publicara predicciones diarias, por provincias, y en formato textual apto para la consola. Mientras buscaba caí en la cuenta de que en su momento no había mirado, al menos no en profundidad, el sitio web de la Agencia Estatal de Metereología, la AEMET, el sitio por excelencia para consultar el parte meteorológico. Tras navegar un poco por su web y acceder a los distintos tipos de información publicada, observé con satisfacción que proporcionaba la información textual por provincias que necesitaba, por lo que podía usarla como base para mi nuevo script de predicción meteorológica.

Aunque lo he estado usando durante muchos meses con éxito, el rudimentario script no pasaba de ser un quick and dirty hack no apto para el consumo, ya que el código tenía hardcoded la consulta para mi provincia de residencia y no contaba con ayuda de uso ni control de errores. Después de dedicar un par de ratos en el último mes a solucionar esos "problemillas" creo que ya puedo compartirlo sin miedo al ridículo:
#!/bin/bash

## taemet - Muestra el parte meteorológico para el día actual según la # 
##          AEMET para la provincia española pasada como argumento     # 
##          v0.2 por Rodia (daltonico.net) 2013                        #

prog=$(basename $0)

function show_usage {
    echo
    echo "Uso: $prog -l | <provincia_sin_acentos_ni_espacios>"
    echo "     -l lista las provincias con la sintaxis requerida"
    echo
}

if [ $# -ne 1 ]; then
    show_usage
    exit 1
fi

browser=$(which w3m)
if [ -z "$browser" ]; then
    echo "$prog: error: falta el programa w3m"
    exit 1
fi

urlbase="http://www.aemet.es/es/eltiempo/prediccion/"
urlquery="provincias?p="

case $1 in
     [aA][cC]oruña) cod_prov="15";;
          [aA]lava) cod_prov="01";;
       [aA]lbacete) cod_prov="02";;
       [aA]licante) cod_prov="03";;
        [aA]lmeria) cod_prov="04";;
       [aA]sturias) cod_prov="33";;
          [aA]vila) cod_prov="05";;
        [bB]adajoz) cod_prov="06";;
      [bB]arcelona) cod_prov="08";;
        [bB]izkaia) cod_prov="48";;
         [bB]urgos) cod_prov="09";;
        [cC]aceres) cod_prov="10";;
          [cC]adiz) cod_prov="11";;
      [cC]antabria) cod_prov="39";;
      [cC]astellon) cod_prov="12";;
          [cC]euta) cod_prov="51";;
  [cC]iudad[rR]eal) cod_prov="13";;
        [cC]ordoba) cod_prov="14";;
         [cC]uenca) cod_prov="16";;
    [eE]l[hH]ierro) cod_prov="384";;
     [fF]ormentera) cod_prov="073";;
  [fF]uerteventura) cod_prov="352";;
       [gG]ipuzkoa) cod_prov="20";;
         [gG]irona) cod_prov="17";;
        [gG]ranada) cod_prov="18";;
 [gG]ran[cC]anaria) cod_prov="353";;
    [gG]uadalajara) cod_prov="19";;
         [hH]uelva) cod_prov="21";;
         [hH]uesca) cod_prov="22";;
          [iI]biza) cod_prov="073";;
           [jJ]aen) cod_prov="23";;
    [lL]a[gG]omera) cod_prov="382";;
      [lL]anzarote) cod_prov="351";;
     [lL]a[pP]alma) cod_prov="383";;
     [lL]a[rR]ioja) cod_prov="26";;
           [lL]eon) cod_prov="24";;
         [lL]leida) cod_prov="25";;
           [lL]ugo) cod_prov="27";;
         [mM]adrid) cod_prov="28";;
         [mM]alaga) cod_prov="29";;
       [mM]allorca) cod_prov="072";;
        [mM]elilla) cod_prov="52";;
        [mM]enorca) cod_prov="071";;
         [mM]urcia) cod_prov="30";;
        [nN]avarra) cod_prov="31";;
        [oO]urense) cod_prov="32";;
       [pP]alencia) cod_prov="34";;
     [pP]ontevedra) cod_prov="36";;
      [sS]alamanca) cod_prov="37";;
        [sS]egovia) cod_prov="40";;
        [sS]evilla) cod_prov="41";;
          [sS]oria) cod_prov="42";;
      [tT]arragona) cod_prov="43";;
       [tT]enerife) cod_prov="381";;
         [tT]eruel) cod_prov="44";;
         [tT]oledo) cod_prov="45";;
       [vV]alencia) cod_prov="46";;
     [vV]alladolid) cod_prov="47";;
         [zZ]amora) cod_prov="49";;
       [zZ]aragoza) cod_prov="50";;
                -l) echo
                    sed -n '/\[aA\]\[cC\]/,/\[zZ\]aragoza/p' $0 | \
                    cut -d')' -f1|tr -d 'A-Z\[\] '| sed 's/^/ /'
                    echo
                    exit 0;;
                 *) show_usage
                    exit 1;;
esac

$browser -dump $urlbase$urlquery$cod_prov > /tmp/$prog.$$ 2> /dev/null

if [ $? -ne 0 ]; then
    echo "$prog: error: no se pudo conectar con $urlbase"
    exit 1
fi

echo

sed -n '/^[A-Z][A-Z][A-Z,. ]*$/,/Seleccione Provincia/p' /tmp/$prog.$$ \
       | head -n -1 | sed 's/Temperatura/Temp./g'

exit $?
Como curiosidad comentar un par de cosas. La lista de códigos de provincia está generada a partir del código HTML de la página web de la AEMET usando filtros estándares de Linux como grep, cut y sed, junto a algunas funcionalidades del editor utilizado, vim. La ayuda al usuario que lista las provincias/islas disponibles y la sintaxis a utilizar la he generado usando los filtros sed, cut y tr a partir del bloque case del propio código del script (chulo que es uno, al menos de vez en cuando ;)