inotify 和 bash

Posted

技术标签:

【中文标题】inotify 和 bash【英文标题】:inotify and bash 【发布时间】:2011-09-24 22:50:03 【问题描述】:

我正在尝试使用 inotify-tools 制作一个 bash 脚本,该脚本将监视目录并通过删除包含“EE”的行来更改所有新文件。一旦更改,它会将文件移动到另一个目录

    #!/bin/sh
    while inotifywait -e create /home/inventory/initcsv; do
      sed '/^\"EE/d' Filein > fileout #how to capture File name?
      mv fileout /home/inventory/csvstorage
    fi
    done

请帮忙?

【问题讨论】:

fi 不是错误的吗? 是的,我认为应该是done 【参考方案1】:

默认情况下,inotifywait -e CREATE 的文本输出格式为

     watched_filename CREATE event_filename

其中watched_filename 代表/home/inventory/initcsvevent_filename 代表新文件的名称。

所以,代替您的 while inotifywait -e ... 行,输入:

    DIR=/home/inventory/initcsv
    while RES=$(inotifywait -e create $DIR); do
        F=$RES#?*CREATE 

并在您的sed 行中使用$F 作为Filein 名称。请注意,$(...) 构造是与 posix 兼容的进程替换形式(通常使用反引号完成),$RES#pattern 结果等于 $RES,并删除了最短的模式匹配前缀。请注意,模式的最后一个字符是空白。 [查看更新 2]

更新 1 要处理可能包含空格的文件名,请在 sed 行中使用 "$F" 而不是 $F。也就是说,在对 F 值的引用周围使用双引号。

RES=...F=... 的定义不需要使用双引号,但是如果你喜欢使用它们是可以的;例如:F=$RES#?*CREATE F="$RES#?*CREATE " 在处理包含空格的文件名时都可以正常工作。

更新 2 如 Daan 的评论中所述,inotifywait 有一个 --format 参数来控制其输出的形式。用命令

while RES=$(inotifywait -e create $DIR --format %f .)
   do echo RES is $RES at `date`; done

在一个终端和命令中运行

touch a aa; sleep 1; touch aaa;sleep 1; touch aaaa

在另一个终端运行,第一个终端出现如下输出:

Setting up watches.
Watches established.
RES is a at Tue Dec 31 11:37:20 MST 2013
Setting up watches.
Watches established.
RES is aaa at Tue Dec 31 11:37:21 MST 2013
Setting up watches.
Watches established.
RES is aaaa at Tue Dec 31 11:37:22 MST 2013
Setting up watches.
Watches established.

【讨论】:

为什么不直接使用--format %w选项输出,所以只能使用文件名? @Daan,是的,这是有道理的(使用 %f,而不是 %w)。见更新 2 inotifywait -e delete_self aSymlinkFilename 如果符号链接被删除,则仅当其真实文件被删除时才起作用:(,它也不适用于损坏的符号链接:(【参考方案2】:

inotifywait 的输出格式为:

filename eventlist [eventfilename]

如果您的文件名可以包含空格和逗号,则解析起来会很棘手。如果它只包含“健全”的文件名,那么你可以这样做:

srcdir=/home/inventory/initcsv
tgtdir=/home/inventory/csvstorage
inotifywait -m -e create "$directory" |
while read filename eventlist eventfile
do
    sed '/^"EE/d'/' "$srcdir/$eventfile" > "$tgtdir/$eventfile" &&
    rm -f "$srcdir/$eventfile
done

【讨论】:

+1 用于使用 -m 开关。如果您不继续监视更改,脚本将不会处理在处理前一个文件时上传的任何文件。【参考方案3】:

引用 inotifywait 的手册页:

inotifywait will output diagnostic information on standard error and event information  on
   standard  output.  The event output can be configured, but by default it consists of lines
   of the following form:

   watched_filename EVENT_NAMES event_filename

   watched_filename
          is the name of the file on which the event occurred.  If the file is a directory, a
          trailing slash is output.

换句话说,它将文件名打印到标准输出。因此,您需要从标准输出中读取它们并对其进行操作以执行您想要执行的操作。

【讨论】:

以上是关于inotify 和 bash的主要内容,如果未能解决你的问题,请参考以下文章

Linux::Inotify2 和线程

inotify和epoll

inotify和rsync实现数据实时同步

Rsync下行同步+inotify实时同步介绍和部署

inotify,inotify_add_watch() 监控多个目录,c++

Rsync+inotify 实时数据同步 inotify master 端的配置