Linux
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
它可以工作,但它假定您永遠不會將文件移入或移出監視文件夾。它還假設事件成對出現,首先是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 次洗牌一對文件,我從未見過一個亂序事件或事件交錯。當然,這可能取決於文件系統和其他條件。)