inotifywait - 名前を変更したときに古いファイル名と新しいファイル名を取得する

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

うまくいきますが、監視フォルダの内外にファイルを移動しないとします。また、イベントがペアで、まずMoving_fromとMoving_toで来るとします。これが常に正しいかどうかはわかりません(これまでは機能します)。

私はinotifyがクッキーを使ってイベントをリンクすることを読んだ。何とかクッキーにアクセスできますか? Cookieが不足しているため、タイムスタンプを使用してイベントを互いにリンクすることを検討しました。より安定した方法でFROMからTOに移動する方法についてのヒントはありますか?

フルスクリプトハイライト

答え1

私はあなたのアプローチが正しいと考えており、Cookieの追跡はこれを行うための信頼できる方法です。ただし、参照されるinotify-tools(3.14)ソースコードの唯一の場所は、カーネルAPIと一致するヘッダーcookie定義です。struct

端に住むのが好きなら、このパッチ(問題#72)は次に完全に適用可能です。3.14そして、%cイベントクッキーの16進形式指定子を追加します。

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

(3つのスレッドを実行して1組のファイルをそれぞれ10,000回混合する間、順序が間違ったイベントやイベントインターリーブを見たことはありません。もちろん、これはファイルシステムやその他の条件によって異なります。)

関連情報