与 vim 一起使用 inotifywait

ada*_*667 17 vim rsync files inotify

我有一个简单的脚本,用于监视文件的更改并将其与远程复制同步:

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile user@host.domain:./somefile
done
Run Code Online (Sandbox Code Playgroud)

它在 nano 上工作得很好,但在 vim 上失败了。当我使用 nano 时,它输出:

somefile CLOSE_WRITE,CLOSE   
Run Code Online (Sandbox Code Playgroud)

并开始下一个循环,等待另一个版本。

当我使用 vim 时,没有输出,脚本只是以退出代码 0 关闭。

我做了一些研究,发现 close_write 是使用 initofywait 和 vim 的正确参数(首先我想使用修改事件),但由于某种原因它对我来说失败了。

Gil*_*il' 18

编辑器可以遵循多种策略来保存文件。两个主要变体是覆盖现有文件,或写入新文件并将其移动到位。写入新文件并将其移动到位具有一个很好的特性,即在任何时间点,从文件中读取都会为您提供文件的完整版本(一瞬间是旧的,下一瞬间是新的)。如果文件被原地覆盖,则在一段时间内它是不完整的,如果其他程序刚刚访问它或系统崩溃,这将是有问题的。

Nano 显然会覆盖现有文件。您的脚本会检测完成写入(close_write事件)的rsync时间点并在该时间点运行。请注意,如果在 rsync 从第一次保存完成其工作之前快速连续保存两次,则 rsync 可能会获取文件的不完整版本。

另一方面,Vim 使用先写后移动的策略——

echo 'new content' >somefile.new
mv -f somefile.new somefile
Run Code Online (Sandbox Code Playgroud)

旧版本的文件会在新版本移动到位时被删除。此时,inotifywait命令返回,因为它被告知要监视的文件不再存在。(新somefile的文件是同名的不同文件。)如果 Vim 被配置为制作备份文件,将会发生类似于

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile
Run Code Online (Sandbox Code Playgroud)

inotifywait现在会看的备份。

有关文件保存策略的更多信息,请参阅如何在程序运行时进行实时更新?文件权限和保存

可以告诉 Vim 使用覆盖策略:关闭backupcopy选项 ( :set nobackupcopy)。如上所述,这是有风险的。

同时处理保存策略,看目录,滤除close_writemoved_to事件somefile

inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
  if [ "$file" = "somefile" ]; then
    …
  fi
done
Run Code Online (Sandbox Code Playgroud)