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吗?缺少cookie,我考虑过使用时间戳将事件链接在一起。以更可靠的方式获取FROM和TO的任何提示吗?

完整脚本要点

Answers:


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

(通过运行三个线程来每10,000次随机播放一对文件,我从未见过单个乱序事件或事件交织。这当然取决于文件系统和其他条件。)


1
美丽。我以前从未收到过如此详尽和有用的答案。非常感谢!!我认为在正式版本中包含您的补丁程序可能会有助于创建工具,以帮助保持文本文件(html,css,md,...)和引用的资产(jpg,gif,mp4等)之间的一致性。您是否在发送拉取请求?:)
安倍晋三

我希望此功能可以使其成为正式版本,但我尚未对其进行分叉,而且我不确定何时可以花时间进行分叉和更新所有评论(doxygen)。
spuratic先生2014年

将其带到上游真的很酷!
蒂姆·史杜普
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.