#!/bin/bash
# retire.sh
# script para retirar a otro lugar (DESTN) aquellos ficheros
# considerados en desuso porque no han sido accedidos desde
# una fecha determinada (LIMIT)

# Copyright :   EUROGARAN Informatica S.L.   http://www.eurogaran.com
# Este programa se acoge a los terminos de la licencia GPL :
# Se permite su copia y libre redistribucion
# pero sin cambiar su licencia incluso tras haber sido modificado.

# Se ruega poner en conocimiento de  <informatica@eurogaran.com>
# aquellas modificaciones y mejoras que se realicen sobre el mismo.

# DEPENDE DE versiones recientes de  ls  y otras herramientas GNU.
# Simplemente comprobar que admiten los modificadores usados.

#=============================================================================
#>>>> PARAMETRO MODIFICABLE No. 1
# LISTA de directorios a incluir.
# En una misma linea (importante comprobarlo), separados por 1 espacio.
# Consecuentemente, ningún directorio puede tener espacios en medio.
# Por ejemplo :
# INCLU='/root /home/juanjo /home/alberto /home/usuario5'

INCLU='/home/juanjo/tmp'


#>>>> PARAMETRO MODIFICABLE No. 2
# FICHERO de directorios y archivos a excluir. Cada uno en una linea del fichero
# y "entrecomillado" cuando el nombre incluya espacios o caracteres especiales.
# (Ante la duda, entrecomillar la ruta absoluta tal como sale al hacer ls).
# Excluir un directorio arrastra consigo todos sus subdirectorios.

EXCLU='/etc/retirexcep.txt'


#>>>> PARAMETRO MODIFICABLE No. 3
# Fecha a partir de la que se desea conservar los ficheros.
# Los de esa fecha y anteriores seran movidos.
# El formato debe ser año-mes-dia.  Por ejemplo  2005-02-30
# Prestar atencion a no confundir el lugar que ocupa el mes con el del dia.
# No olvidar poner el cero delante del mes o el dia cuando tengan una sola cifra

LIMIT=2006-01-01


#>>>> PARAMETRO MODIFICABLE No. 4
# Nombre del directorio de destino.
# Se recomienda que incluya la fecha, por ejemplo :
# DESTN=/antiguos/no_usados_desde/$LIMIT

DESTN=/tmp/no_usados_desde/$LIMIT


#>>>> PARAMETRO MODIFICABLE No. 5
# Eliminar o no aquellos directorios que se hayan vaciado.
# Peligroso cuando para al menos uno de ellos tenga sentido
# seguir existiendo vacio, como por ejemplo la carpeta papelera /Trash
# dentro del escritorio de usuario, la de documentos, etc.

ELIMINA_DIRS="Afirmativo"
# Descomentar/comentar la siguiente linea para conservar/eliminar
# los directorios vaciados.
# unset ELIMINA_DIRS


#>>>> PARAMETRO MODIFICABLE No. 6
# Crear para cada directorio en origen un enlace o acceso a destino.
# Su principal proposito es eliminar sorpresas/quejas de usuarios
# al no encontrar sus archivos.

ACCESO_DIRECTO="no_usados_desde_$LIMIT"
# Descomentar la siguiente linea para no crear ningun acceso directo
# unset ACCESO_DIRECTO


#>>>> PARAMETRO MODIFICABLE No. 7
# log a archivo
LOGAR=/dev/null
LOGAR=/tmp/retirarlog.txt


#=============================================================================
# Normalmente no debiera ser necesario modificar nada por debajo de esta linea.

mkdir -p $DESTN || exit 1

# Ahora ya se puede convertir la fecha LIMIT a forma estrictamente numeral :
LIMIT=`echo "$LIMIT" | tr -d '-'`

# Se lee el fichero de exclusiones, construyendo un filtro a ser aplicado
# posteriormente :
# El valor inicial del filtro va destinado a evitar los directorios ./ y ../
FILTR=" | grep -ve '^\.$' | grep -ve '^\.\.$'"
TEMPF=`tempfile`
echo "$FILTR" > $TEMPF
cat "$EXCLU" | {
while read; do
  # Se omiten las lineas vacias :
  if [ "$REPLY" ]; then
    if ! [ -e "$REPLY" ]; then
      echo "No existe el archivo o directorio excluido $REPLY"
      echo "Se excluye de todos modos por si apareciese durante la ejecucion."
    fi
    FILTR="$FILTR | grep -v ^$REPLY"
    echo "$FILTR" > $TEMPF
  fi
done
}
FILTR=`cat "$TEMPF"` && rm "$TEMPF"

if ! [ "$LOGAR" ]; then
  LOGAR=/dev/null
fi
echo "El filtro es:$FILTR" > $LOGAR || exit 1


# Se recorren los directorios aplicando el filtro, y dentro de cada
# subdirectorio se recorren los archivos volviendo a aplicar el filtro :
for ORIGN in $INCLU; do
  find $ORIGN -type d | {
    while read; do
      DIRECTORIO_NO_FIGURA_COMO_EXCLUIDO=`sh -c "echo \"$REPLY\"$FILTR"`
      if [ "$DIRECTORIO_NO_FIGURA_COMO_EXCLUIDO" ]; then
        NOMDIR=$REPLY
        echo "Se examina el directorio $NOMDIR" >> $LOGAR
        cd "$NOMDIR"
        ls -1 --color=never | {
          while read; do
            ARCHIVO_NO_FIGURA_COMO_EXCLUIDO=`sh -c "echo \"$REPLY\"$FILTR"`
            if [ "$ARCHIVO_NO_FIGURA_COMO_EXCLUIDO" ]; then
              if ! [ -d "$REPLY" ]; then
                # ls -ult para usar la fecha de acceso
                # ls -lt para usar la de modificacion
                FECHA=`ls -ult "$REPLY" | tr -s '[:space:]'\
                      | cut -d ' ' -f 6 | tr -d '-'`
                if [ "$FECHA" -le "$LIMIT" ] ; then
                  if ! [ -e "$DESTN/$NOMDIR" ]; then
                    mkdir -p "$DESTN/$NOMDIR" &&\
                    chown --reference="$NOMDIR" "$DESTN/$NOMDIR" &&\
                    chgrp --reference="$NOMDIR" "$DESTN/$NOMDIR" &&\
                    chmod --reference="$NOMDIR" "$DESTN/$NOMDIR" &&\
                    getfacl "$NOMDIR" |\
                    setfacl --set-file=- "$DESTN/$NOMDIR" 2>&1 >> $LOGAR &&\
                    echo "Se ha creado el directorio $DESTN/$NOMDIR" >> $LOGAR ||\
                    echo "No se ha podido crear el directorio $DESTN/$NOMDIR" >> $LOGAR
                    if [ "$ACCESO_DIRECTO" ]; then
                      if ! [ -e "$ORIGN/$ACCESO_DIRECTO" ]; then
                        ln -s "$DESTN/$ORIGN" "$ORIGN/$ACCESO_DIRECTO"
                      fi
                    fi
                  fi
                  # Borrar solamente tras haber copiado equivale y proporciona
                  # mayor seguridad que mover (cortes de corriente, etc.)
                  # y permite reproducir las ACLs
                  cp -dp "$REPLY" "$DESTN/$NOMDIR" &&\
                  getfacl "$REPLY" |\
                  setfacl --set-file=- "$DESTN/$NOMDIR/$REPLY" 2>&1 >> $LOGAR &&\
                  echo "Se ha copiado el archivo $NOMDIR/$REPLY" >> $LOGAR \
#                  && rm -f "$REPLY" && echo "Se ha borrado el original." >> $LOGAR
                # Descomentar/comentar la linea anterior para activar/desactivar
                # el borrado.
                # Importante :  Nunca escribir comentarios por encima de ella.
                fi
              fi
            fi
          done
        }
        cd -
      fi
    done
  }
done
echo "Procesamiento de archivos finalizado." >> $LOGAR

if [ "$ELIMINA_DIRS" ]; then
  echo "Se eliminan todos aquellos directorios que hayan quedado vacios." >> $LOGAR
  for ORIGN in $INCLU; do
  # Se debe proceder de abajo arriba (-depth), justo al contrario de antes :
    find $ORIGN -type d -depth | {
      while read; do
        if [ -e "$DESTN/$REPLY" ]; then
          # Si quedan archivos, simplemente no hace nada, pero no indicar error.
          rmdir "$REPLY" --ignore-fail-on-non-empty
        fi
      done
    }
  done
fi

