我使用的是 Ubuntu 20.04。我正在尝试运行这个脚本inotifywait
。这个想法是每次目录发生变化时将文件从 移动dir
到;target
该脚本是一个 shell 文件,可以自动启动或通过命令行手动启动。
#!/usr/bin/env bash
dir=/mnt/test1/test/ #ftp point of mount
target=/var/www/html/local/ #normal directory on filesystem
inotifywait -m "$dir" --format "%w%f" -e create -e moved_to |
while read path action file; do
mv "$file" "$target"
done
并且要移动的文件需要具有*.txt
格式。 inotify 正在监视,但是当我使用 ftp 客户端将文件放入dir
并等待 inotify 将其移动到 时target
,该文件没有任何反应。
答案1
不幸的是,该inotify
API 不能用于监控远程文件系统。
Inotify 仅报告用户空间程序通过文件系统 API 触发的事件。因此,它不会捕获网络文件系统上发生的远程事件。 (应用程序必须回退到轮询文件系统以捕获此类事件。)
相关问题:
也就是说,您问题中的脚本无论如何都不会按预期工作。
"%w%f"
使用as 的输出格式的想法inotifywait
是为循环中的命令提供触发侦听的文件系统事件的文件的完整路径。%w
扩展为监视文件的路径($dir
目录),并%f
扩展为导致事件的文件的(基本)名称。
因此,inotifywait
仅为其捕获的每个事件发出一个完整路径。另一方面,你的read
命令已发出三要填写的变量:path
、action
和file
.默认情况下,read
根据中的字符分割读取行IFS
,并将结果标记分配给作为参数给出的名称:第一个标记分配给第一个名称,第二个标记分配给第二个名称,等等。(并且,如果有比倒数第二个名字之后的名字更多的标记,所有剩余的标记都分配给姓氏)。
正如您可以轻松检查的那样,在代码中,触发监视事件的任何文件的完整路径都被分配给path
(除非它包含空白字符):
$ inotifywait -m --format "%w%f" -e create -e moved_to /tmp/test |
while read path action file; do
printf 'path: "%s"; action: "%s"; file: "%s"\n' "$path" "$action" "$file"
done
# Type "touch /tmp/test/foo" in a different terminal
path: "/tmp/test/foo"; action: ""; file: ""
另外,正如一文中指出的不同的答案在您签署的问答中,您应该监听close_write
事件,而不是监听create
。您可能正在寻找的是:
inotifywait -m -q --format "%w%f" -e close_write -e moved_to -- "$dir" |
while IFS= read -r src; do
if [ "${src##*.}" = 'txt' ]; then
mv -- "$src" "$target"
fi
done
-r
告诉read
不要解释反斜杠转义序列。IFS=
用于防止read
修剪文件名末尾的空白字符(以处理名称以空格或制表符结尾的不太可能的情况)。
请注意,对于名称包含换行符的文件,这仍然会失败。