Cómo realizar una tarea cuando se agrega un archivo nuevo a un directorio en Linux

Este tutorial le mostrará cómo usar los eventos del sistema de archivos de Linux (notificar) para recibir notificaciones cada vez que aparece un archivo en un directorio. Puede utilizarlos como disparadores para automatizar tareas comunes en su sistema.

Vamos a escribir un script que observe un directorio y actúe sobre los archivos nuevos que se agregan. Cada archivo se comprime con gzip y se mueve a otro directorio, tan pronto como se detecta. El script usa el subsistema inotify, a través de una utilidad llamada inotify-tools. Pero primero, instalemos la herramienta y experimentemos.

Instalación de inotify-tools y gzip

Use apt-get para instalar este paquete en su sistema si está usando Ubuntu u otra distribución basada en Debian. En otras distribuciones de Linux, utilice la herramienta de administración de paquetes de su distribución de Linux.

sudo apt-get install inotify-tools gzip

Experimentando con inotify-tools

Comencemos por observar un directorio y ver qué eventos se inician cuando llegan nuevos archivos. Usaremos una herramienta llamada inotifywatch, que forma parte de inotify-tools. Cree un nuevo directorio llamado «entrante»:

mkdir incoming

Comience a ver este directorio ejecutando el siguiente comando:

inotifywatch -v incoming

Esto le indicará a inotify que observe todos los eventos del sistema de archivos en el directorio «entrante». La opción -v hace que la herramienta imprima información adicional sobre lo que está haciendo. No hemos especificado una opción de tiempo de espera (-t), y el comando seguirá recopilando eventos hasta que salgamos con CTRL + C. En este punto, nuestra terminal debería verse así:

  Cómo instalar Solus Linux

Abra una nueva ventana de terminal (o pestaña) y cambie al directorio entrante. Utilice el comando táctil para crear un nuevo archivo llamado «newfile».

cd incoming/
touch newfile

Ahora regrese a la primera ventana de terminal y detenga inotifywatch presionando CTRL + C.

Se entregará una tabla de eventos a la consola, indicando una instancia de «crear», «abrir», «attrib» y «cerrar_escribir». Estos cuatro eventos ocurrieron cuando usamos la función táctil para crear un nuevo archivo, establecimos sus atributos de acceso al archivo, lo abrimos para escribir un carácter de terminación nulo y luego lo cerramos. Estos son solo algunos de la multitud de eventos que se pueden monitorear en un sistema de archivos con inotify-tools. Puede ver la lista completa en la página principal de inotifywatch.

Para nuestros propósitos, solo nos interesan dos eventos:

«Crear»: cuando se crea un archivo en el directorio de destino.
«Moved_to»: cuando un archivo se mueve desde otra ubicación al directorio de destino.

Intentemos inotifywatch nuevamente, pero esta vez indicándole que monitoree estos dos eventos solamente. Ejecute este comando en la primera ventana de terminal:

inotifywatch -v -e create -e moved_to incoming

En la segunda ventana o pestaña de la terminal, intentemos crear un nuevo archivo, cambiar su contenido y luego mover el archivo desde otra ubicación al directorio de destino. Todos estos comandos se ejecutan desde el directorio de inicio.

touch incoming/created
echo Testing123 >> incoming/created
touch /tmp/created2
mv /tmp/created2 incoming/

Regrese a la primera ventana de terminal y detenga inotifywatch presionando CTRL + C. Veremos el siguiente resultado:

  Cómo instalar el cliente PuTTy SSH en Linux

Solo se contaron dos eventos: crear un archivo llamado «created.txt» y mover un archivo existente llamado «created2.txt». Todo lo demás, como la modificación de «created.txt», fue ignorado.

Ver un directorio y ejecutar una tarea

Ahora que sabemos qué eventos seguir, podemos usar otra herramienta llamada inotifywait para bloquear la ejecución hasta que se cree un archivo o se mueva a nuestro directorio de destino. Usaremos los mismos argumentos que usamos con inotifywatch y también especificaremos cómo queremos que se formatee el nombre del archivo para usarlo en nuestra tarea.

Antes de comenzar, necesitamos un directorio para contener los archivos que ya se han procesado. Cree un directorio llamado «procesado»:

mkdir processed

A continuación, cree una nueva secuencia de comandos llamada «watch-incoming.sh» y agregue los contenidos que se enumeran a continuación:

#!/bin/bash

TARGET=~/incoming/
PROCESSED=~/processed/

inotifywait -m -e create -e moved_to --format "%f" $TARGET 
        | while read FILENAME
                do
                        echo Detected $FILENAME, moving and zipping
                        mv "$TARGET/$FILENAME" "$PROCESSED/$FILENAME"
                        gzip "$PROCESSED/$FILENAME"
                done

El script ejecuta el comando inotifywait con la opción -m. Esto hace que el monitor de comandos cambie indefinidamente. Cada vez que se detecta un nuevo evento, el nombre del archivo se pasa al comando de lectura y se inyecta en la variable «FILENAME». Se ejecuta el bloque debajo del ciclo while, en el que el archivo se mueve primero al directorio «procesado» y luego se comprime con gzip. El archivo original se reemplaza por el archivo comprimido y el nombre del archivo terminará en «.gz».

  Cómo obtener la última versión de Mozilla Thunderbird para Linux

Concedamos permisos de ejecución en este script y ejecútelo desde nuestro directorio personal.

chmod u+x watch-incoming.sh
./watch-incoming.sh

Abra la segunda ventana de terminal y cree un nuevo archivo en el directorio «entrante». Enumere el contenido del directorio «entrante» y «procesado» para ver los resultados del evento detectado:

El archivo de texto sin procesar que copiamos en el directorio «entrante» fue detectado por el script, copiado en «procesado» y luego comprimido usando gzip.

Podemos hacer algunas tareas interesantes ahora que podemos estar atentos a la llegada de nuevos archivos a un directorio. Por ejemplo, podríamos agregar una marca de agua a los archivos de imagen, comprimir videos sin procesar en formato mp4 e incluso cargar cada archivo nuevo que vemos en un bucket de Amazon S3. Este script es un buen punto de partida para implementar sus propios flujos de trabajo y automatizar tareas comunes en su sistema.