inotifywait - obtiene el nombre de archivo antiguo y nuevo al cambiar el nombre

8

Estoy buscando una forma confiable de detectar el cambio de nombre de los archivos y obtener nombres de archivos antiguos y nuevos. Esto es lo que tengo hasta ahora:

COUNTER=0;
inotifywait -m --format '%f' -e moved_from,moved_to ./ | while read FILE
do
if [ $COUNTER -eq 0 ]; then
    FROM=$FILE;
    COUNTER=1;
else
    TO=$FILE;
    COUNTER=0;
    echo "sed -i 's/\/$FROM)/\/$TO)/g' /home/a/b/c/post/*.md"
    sed -i 's/\/'$FROM')/\/'$TO')/g' /home/a/b/c/post/*.md
fi
done

Funciona, pero supone que nunca moverá archivos dentro o fuera de la carpeta observada. También supone que los eventos vienen en pares, primero moved_from, luego moved_to. No sé si esto siempre es cierto (funciona hasta ahora).

He leído que inotify usa una cookie para vincular eventos. ¿Se puede acceder a la cookie de alguna manera? Al carecer de la cookie, pensé en usar marcas de tiempo para vincular eventos. ¿Algún consejo para llegar DESDE y HACIA DE una manera más confiable?

Guión completo .

abe
fuente

Respuestas:

6

Creo que su enfoque es correcto, y el seguimiento de la cookie es una forma sólida de hacerlo. Sin embargo, el único lugar en el origen de inotify-tools (3.14) al que cookiese hace referencia es en el encabezado que define la structAPI del núcleo.

Si le gusta vivir al límite, este parche ( problema # 72 ) se aplica limpiamente a 3.14 y agrega un %cespecificador de formato para la cookie de evento en hexadecimal:

--- libinotifytools/src/inotifytools.c.orig     2014-10-23 18:05:24.000000000 +0100
+++ libinotifytools/src/inotifytools.c  2014-10-23 18:15:47.000000000 +0100
@@ -1881,6 +1881,12 @@
                        continue;
                }

+               if ( ch1 == 'c' ) {
+                       ind += snprintf( &out[ind], size-ind, "%x", event->cookie);
+                       ++i;
+                       continue;
+               }
+
                if ( ch1 == 'e' ) {
                        eventstr = inotifytools_event_to_str( event->mask );
                        strncpy( &out[ind], eventstr, size - ind );

Este cambio modifica libinotifytools.so, no el inotifywaitbinario. Para probar antes de la instalación:

LD_PRELOAD=./libinotifytools/src/.libs/libinotifytools.so.0.4.1 \
  inotifywait  --format="%c %e %f" -m -e move /tmp/test
Setting up watches.
Watches established.
40ff8 MOVED_FROM b
40ff8 MOVED_TO a

Asumiendo que MOVED_FROM siempre ocurre antes de MOVED_TO (lo hace, vea fsnotify_move(), y es una cola ordenada , aunque los movimientos independientes pueden intercalarse) en su script, almacena en caché los detalles cuando ve una línea MOVED_FROM (tal vez en una matriz asociativa indexada por ID), y ejecuta tu procesamiento cuando veas un MOVED_TO con la mitad coincidente de la información.

declare -A cache
inotifywait  --format="%c %e %f" -m -e move /tmp/test |
while read id event file; do
    if [ "$event" = "MOVED_FROM" ]; then
        cache[$id]=$file
    fi
    if [ "$event" = "MOVED_TO" ]; then
        if [ "${cache[$id]}" ]; then
            echo "processing ..."
            unset cache[$id]
        else
            echo "mismatch for $id"
        fi
    fi
done

(Con tres subprocesos ejecutándose para mezclar un par de archivos cada 10,000 veces, nunca vi un solo evento fuera de orden o intercalado de eventos. Puede depender del sistema de archivos y otras condiciones, por supuesto).

Sr. púrpura
fuente
1
Hermoso. Nunca recibí una respuesta tan detallada y útil antes. ¡¡Muchas gracias!! Creo que la inclusión de su parche en la versión oficial podría facilitar la creación de herramientas que ayuden a mantener la coherencia entre los archivos de texto (html, css, md, ...) y los recursos referidos (jpg, gif, mp4, ...). ¿Estás enviando una solicitud de extracción? :)
ae
Espero que esta característica llegue a la versión oficial, pero no la he bifurcado, y no estoy seguro de cuándo encontraré el tiempo para bifurcar y actualizar todos los comentarios (doxygen).
Sr.Spuratic
¡Sería genial tener esto en la corriente!
Tim Stoop