让我们假设我们有一个空文件夹,我们在其中创建以下Bash脚本:
String example = "Here you can have anything";
基本上,它等待修改/移动/创建/删除该目录中的文件,然后,如果文件#!/bin/bash
while true; do
inotifywait -r -e modify,move,create,delete $(dirname $0)
if [ -f 'asdf.txt' ]; then
echo "YES!"
else
echo "NO!"
fi
# Do something that takes some time...
sleep 0.1
done
存在,则将asdf.txt
输出到输出。
现在让我们创建YES!
文件并运行Bash脚本。在脚本运行的情况下,如果我使用Vim编辑asdf.txt
并对其进行更改,那么我可以看到asdf.txt
检测到CREATE
事件,但我得到的唯一输出是{{1 }}。这是为什么?对于我尝试过的其他编辑来说,情况并非如此。
请注意,如果我在inotifywait
和文件测试之间添加一个小延迟,它就可以正常工作:
NO!
有没有办法在用Vim编辑文件后测试文件,而不必在脚本中添加任意延迟?
这与Vim的交换文件有关。事实上,如果您编辑inotifywait
并告诉Vim避免创建交换文件,则不会发生这种情况。
但是,此脚本将由最终用户运行,我不能指望它们具有任何特定的Vim配置(也不要求它们避免交换文件或更改交换文件的默认目录)。
我怀疑应该有一种方法可以使用[...]
inotifywait ...
sleep 0.01
if [-f 'asdf.txt' ]; ...
[...]
中的vimrc
选项,但我还没有成功使用它(尝试使用--exclude
)。
答案 0 :(得分:1)
不要将inotifywait
放在循环中,而是使用监视选项并将输出传递给循环,如下所示:
while IFS= read -r -u 5 EVENT
do
(PARSE EVENT)
if [ (I am interested in that file) ]; then
echo "YES!"
else
echo "NO!"
fi
# Do something that takes some time...
# Do not sleep
done 5< <(inotifywait -m ....)
上面的代码使用文件描述符5来保护标准输入,以防你的“某事”需要用户输入。
一个优点是,您将接收在“需要一些时间”的事情发生时发生的事件。如果您想避免接收事件的延迟,您可能希望在后台执行“某事”(使用&
)。
答案 1 :(得分:0)
在保存对文件的更改时,Vim实际上做了很多事情:
./ CREATE 4913
./ DELETE 4913
./ MOVED_FROM asdf.txt
./ MOVED_TO asdf.txt~
./ CREATE asdf.txt
./ MODIFY asdf.txt
./ DELETE asdf.txt~
./ MODIFY .asdf.txt.swp
[...]
实际上可能会有一些预期(比如创建和编辑交换和备份文件)。但有些可能有点违反直觉:
4913
验证它可以在您看到该文件的目录中创建一个文件
并设置uid / gid。创建适当的规则并在选择事件inotifywait
时更具限制性将触发,我们可以使用:
inotifywait --exclude ".*\.(swp|swx)|4913|.*~" -r -e modify,moved_to,create,delete $(dirname $0)
请注意,我们已经忘记了moved_from
个事件。
这可以与Fred's answer结合使用,将Vim编辑视为特殊情况(即:当我们第一次看到正在创建的4913
文件时。)