Revista Informática

Descompresión de ficheros automática en Linux con bash

Publicado el 22 junio 2016 por Drassill
Hola a todos; hoy primer día de Verano, quiero traeros un pequeño script diseñado para "vagos" que no quiere recordar toda la sintaxis relacionada con la descompresión de archivos. Existen numerosos formatos de compresión y a veces el recordarlo todos puede resultar difícil; especialmente cuando trabajamos con ficheros basados en tar; obligándonos a consultar por Internet u otras fuentes la sintaxis de descompresión correcta. ¿Pero para qué tener que recordar dicha sintaxis cuando podemos hacer que un script o servicio lo haga por nosotros? Es por eso que trasteando un poco finalmente he creado una pequeña solución que puede facilitarnos considerablemente dicha tarea; en este caso en concreto he creado un demonio (un servicio) que descomprima automáticamente un fichero. Si bien podemos hacer que simplemente sea un script que se ejecute únicamente cuando queremos.
Portada_bash
Para ello lo primero que he creado ha sido el script que inicializará y detendrá el demonio; un script que incluiremos en el directorio /etc/init.d para que, en caso de ser necesario, se inicializará automáticamente el arranque. A dicho script lo he llamado demonio_dcompres.sh y tendría el siguiente contenido:
  1. #!/bin/bash
  2. ### BEGIN INIT INFO
  3. # Provides:          dcompres
  4. # Required-Start:    $network $named $remote_fs $syslog
  5. # Required-Stop:     $network $named $remote_fs $syslog
  6. # Default-Start:     2 3 4 5
  7. # Default-Stop:      0 1 6
  8. # Short-Description: dcompres
  9. # Description:       Descompresor automatico
  10. ### END INIT INFO
  11. PIDFILE=/tmp/dcompres.pid
  12. SRV="dcompres"
  13. function status()
  14. if [ -f ${PIDFILE} ];
  15. then
  16.         echo "${SRV}  esta en marcha"
  17. else
  18.         echo "${SRV} esta parado"
  19. fi
  20. function start(){
  21.  echo -n $"Iniciando servicio ${SRV}: "
  22.  /usr/bin/dcompres >/dev/null 2>&1 &
  23.  RETVAL=$?
  24.  echo $! > $PIDFILE
  25.  if [ ${RETVAL} -eq 0 ];
  26.  then
  27.         echo "Se ha iniciado ${SRV}"
  28.  else
  29.         echo "No se ha podido iniciar ${SRV}"
  30.  fi
  31.  echo
  32. }
  33. function stop(){
  34.  echo -n $"Parando servicio ${SRV}... "
  35.  SERV=$(ps -e |grep ${SRV} |awk '{print $1}')
  36.  kill -9 ${SERV}
  37.  echo "Servicio detenido"
  38. }
  39. function restart(){
  40.  stop
  41.  sleep 10
  42.  start
  43. }
  44. case "$1" in
  45. start)
  46.  start
  47.  ;;
  48. stop)
  49.  stop
  50.  ;;
  51. restart)
  52.  restart
  53.  ;;
  54. status)
  55. status
  56. ;;
  57. *)
  58.  echo $"Usar: $0 {status|start|stop|restart}"
  59.  exit 1
  60. esac
  61. exit 0

Si observáis bien, este script controla otro llamado /usr/bin/dcompres, script que controlaremos como un servicio gracias a este script añadido en init.d. Dicho script puede ser más o menos complicado dependiendo de nuestras necesidades; en este caso he creado un script bastante completo que intenta contemplar diferentes posibilidades, que sería el siguiente
  1. #!/bin/bash
  2. #BUCLE INFINTO HASTA QUE LO PAREMOS
  3. ACTIVE='y'
  4. DIRECTORIO='/home/ivan/Descargas/'
  5. while [ ${ACTIVE} == 'y' ];
  6. do
  7.         cd $DIRECTORIO
  8.         ls $DIRECTORIO |grep ".tar" > /tmp/descom.txt
  9.         ls $DIRECTORIO |grep ".bz2" >> /tmp/descom.txt
  10.         ls $DIRECTORIO |grep ".gz" >> /tmp/descom.txt
  11.         ls $DIRECTORIO |grep ".rar" >> /tmp/descom.txt
  12.         ls $DIRECTORIO |grep ".zip" >> /tmp/descom.txt
  13.         while read FICHERO
  14.         do
  15.                 FICHERO2=`echo $FICHERO | sed 's/ /_/g'`
  16.                 if [ "$FICHERO" !"$FICHERO2" ];
  17.                 then
  18.                         mv "$FICHERO" $FICHERO2
  19.                 fi
  20.                 #TAR
  21.                 if [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 1 | rev) == "tar" ];
  22.                 then
  23.                         tar -xvf $FICHERO2
  24.                         rm ${FICHERO2}
  25.                 #BZ2 Y TAR.BZ2
  26.                 elif [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 1 | rev) == "bz2" ];
  27.                 then
  28.                         if [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 2 | rev) == "tar" ];
  29.                         then
  30.                                 tar -xjf  $FICHERO2
  31.                         else
  32.                                 bzip2 -d $FICHERO2
  33.                         fi
  34.                         rm ${FICHERO2}
  35.                 #GZ Y TAR.GZ
  36.                 elif [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 1 | rev) == "gz" ];
  37.                 then
  38.                         if [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 2 | rev) == "tar" ];
  39.                         then
  40.                                 tar -xzf  $FICHERO2
  41.                         else
  42.                                 gzip -d $FICHERO2
  43.                         fi
  44.                         rm ${FICHERO2}
  45.                 #RAR
  46.                 elif [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 1 | rev) == "rar" ];
  47.                 then
  48.                         rar -x $FICHERO2
  49.                         rm ${FICHERO2}
  50.                 #ZIP
  51.                 elif [ $(ls $DIRECTORIO$FICHERO2 | rev | cut -d'.' -f 1 | rev) == "zip" ];
  52.                 then
  53.                         unzip $FICHERO2
  54.                         rm ${FICHERO2}
  55.                 fi
  56.         done < /tmp/descom.txt
  57. done

En este script hay un par de puntos "especiales" que en mi opinión merecen la pena ser mencionados. El primer punto sería el uso de la variable FICHERO2 con sed. Por si no encontraseis dicha línea os la pondré a continuación:
  1. FICHERO2=`echo $FICHERO | sed 's/ /_/g'`
  2. if [ "$FICHERO" !"$FICHERO2" ];
  3. then
  4.     mv "$FICHERO" $FICHERO2
  5. fi

Esta acción tiene un motivo en concreto. Imaginemos que el fichero comprimido que tenemos en el directorio contiene espacios; dichos espacios no dejará trabajar con el fichero adecuadamente, así que lo primero que haríamos sería transformar los espacios en blanco en _. Obviamente, revisaríamos si el fichero tendría espacios para evitar renombrar el fichero en vano; he ahí el motivo del if. El comando de sustitución tiene la sintaxis:
FICHERO_NUEVO=`echo$FICHERO_ORIGINAL|sed's/CADENA_ORIGINAL/CADENA_NUEVA/g'`
Otro punto que a tener en cuenta en el que probablemente os habréis fijado es que hago uso del parámetro |rev en las condiciones introducidas. El uso de dicho rev es debido a que con ello nos aseguraremos que siempre contará los puntos desde el final del fichero y no desde el principio; puntos que uso en este script como referencia para obtener el tipo de compresión (zip, tar, rar...). Esto es debido a que existen muchos ficheros que contienen la versión junto con su nombre (ejemplo nmap-7.12.tar.bz2) y siempre querremos asegurarnos que contaremos el último o penúltimo punto (dependiendo de nuestra necesidad), independientemente de los puntos que hayamos encontrado antes. La sintaxis sería:
ls fichero |rev|cut-d'.'-f(número_posición_desde_el_final)|rev
Si pusiésemos un 1, haríamos referencia a la última posición, mientras que con un 2 haríamos referencia a la penúltima y así sucesivamente...
Con esto tendríamos un script muy sencillo y funcional que hará que las dificultades de una tarea de descompresión, sean tareas del pasado.
Espero que os haya resultado útil.
Saludos.

Volver a la Portada de Logo Paperblog