inotifywait - получить старое и новое имя файла при переименовании

8

Я ищу надежный способ обнаружить переименование файлов и получить как старые, так и новые имена файлов. Это то, что я до сих пор:

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

Это работает, но предполагает, что вы никогда не будете перемещать файлы в или из просматриваемой папки. Также предполагается, что события происходят парами: сначала Move_from, а затем Move_to. Я не знаю, всегда ли это так (пока работает).

Я прочитал, что inotify использует куки для связи событий. Доступен ли файл cookie как-нибудь? Не имея cookie, я подумал об использовании временных меток для связи событий. Любые советы по получению ОТ и ТО более надежным способом?

Полный сценарий .

Abe
источник

Ответы:

6

Я думаю, что ваш подход правильный, и отслеживание cookie - надежный способ сделать это. Однако единственное место в источнике inotify-tools (3.14), на cookieкоторое ссылаются, находится в заголовке, определяющем, structчтобы соответствовать API ядра.

Если вам нравится жить на грани, этот патч ( выпуск № 72 ) чисто применяется к 3.14 и добавляет %cспецификатор формата для файла cookie события в шестнадцатеричном формате:

--- 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 );

Это изменение изменяет libinotifytools.so, а не inotifywaitдвоичный файл. Чтобы проверить перед установкой:

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

Предполагая, что MOVED_FROM всегда происходит перед MOVED_TO (это происходит, видите fsnotify_move(), и это упорядоченная очередь , хотя независимые перемещения могут чередоваться) в вашем скрипте вы кэшируете детали, когда видите строку MOVED_FROM (возможно, в ассоциативном массиве, индексированном по ID), и запустите обработку, когда увидите MOVED_TO с соответствующей половиной информации.

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

(С тремя потоками, работающими для перетасовки пары файлов каждые 10000 раз, я никогда не видел ни одного неупорядоченного события или чередования событий. Конечно, это может зависеть от файловой системы и других условий.)

mr.spuratic
источник
1
Прекрасный. Я никогда не получал такой подробный и полезный ответ раньше. Огромное спасибо!! Я думаю, что включение вашего патча в официальную версию может облегчить создание инструментов, которые помогают поддерживать согласованность между текстовыми файлами (html, css, md, ...) и ссылочными ресурсами (jpg, gif, mp4, ...). Вы отправляете запрос на удаление? :)
'20
Я надеюсь, что эта функция войдет в официальную версию, но я не разветвлял ее, и я не уверен, когда найду время, чтобы раскошелиться и обновить все комментарии (doxygen).
mr.spuratic
Было бы здорово получить это в апстриме!
Тим Ступ