Linux

inotifywait - 重命名時獲取新舊文件名

  • June 29, 2017

我正在尋找一種可靠的方法來檢測文件重命名並獲取新舊文件名。這是我到目前為止所擁有的:

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

它可以工作,但它假定您永遠不會將文件移入或移出監視文件夾。它還假設事件成對出現,首先是moved_from,然後是moved_to。我不知道這是否總是正確的(到目前為止有效)。

我讀到 inotify 使用 cookie 來連結事件。cookie 是否可以通過某種方式訪問?由於缺少 cookie,我考慮使用時間戳將事件連結在一起。以更可靠的方式獲取 FROM 和 TO 的任何提示?

完整的腳本要點

我認為您的方法是正確的,並且跟踪 cookie 是一種可靠的方法。但是,在 inotify-tools (3.14) 的原始碼中唯一cookie被引用的位置是在定義struct與核心 API 匹配的標頭中。

如果你喜歡生活在邊緣,這個更新檔(問題 #72)完全適用於3.14,並為十六進制的事件 cookie 添加%c格式說明符:

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

(三個執行緒分別執行 10,000 次洗牌一對文件,我從未見過一個亂序事件或事件交錯。當然,這可能取決於文件​​系統和其他條件。)

引用自:https://unix.stackexchange.com/questions/163749