与vim一起使用inotifywait


14

我有一个简单的脚本,可以监视文件的更改并将其与远程副本同步:

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile user@host.domain:./somefile
done

它在nano上工作正常,但在vim上工作失败。当我使用nano时,它输出:

somefile CLOSE_WRITE,CLOSE   

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

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

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


这个对我有用。您确实在保存文件之前在vim中进行过更改,而不仅仅是打开文件进行编辑?
roaima

@roaima仅在backupcopy关闭该选项时有效。
吉尔斯(Gilles)'所以

Answers:


15

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

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

另一方面,Vim使用“先写后移”策略,这可以达到以下目的:

echo 'new content' >somefile.new
mv -f somefile.new somefile

文件的旧版本会发生什么变化,即在将新版本移到适当位置时将其删除。此时,inotifywait命令返回,因为已告知要监视的文件不再存在。(新somefile文件是具有相同名称的另一个文件。)如果已将Vim配置为制作备份文件,则将发生类似

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile

并且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

这里提出的方法的缺点是,当您“一次”写入多个文件时,每个文件将运行一次命令。我正在编辑代码,因此我可以修改标题和其他几个翻译单元和:wa。然后,对于每个写入的文件,我的构建都会运行一次。
有限赎罪

@LimitedAtonement与这个问题相比,使用案例要复杂得多。对于您的用例,您需要在保存一个文件后稍等片刻。文件永远不会真正“立即”被修改。如果使用保存多个文件,则将:wa得到连续的inotify事件。您需要在第一个之后等待,看看其他人是否还会来。但您可以使用此处提供的代码:额外的复杂性将包含在中
吉尔斯(Gillles)“所以-别再作恶了”

我决定了@Gilles while true; do inotifywait ... [no -m]; make; sleep .1; done;。有一些陷阱,但我得出了一些可行的建议。
限量赎罪
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.