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

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

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? Не имея куки, я думал об использовании временных меток для объединения событий вместе. Любые советы по получению ОТ и ТО более надежным способом?

Полный скрипт .

Я думаю, что ваш подход правильный, и отслеживание 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 файл 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 

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