1

Mentioned here as well: https://stackoverflow.com/questions/13312794/inotify-dont-treat-vim-editting-as-a-modification-event

Really frustrating issue, how can I force vim to write the file?

It seems Vim does something strange when writing a file. It does not seem to invoke any of the [Create, Modify, CloseWrite, Move] inotify events. Only initially. on the first change.

Seems that it "deletes" the file, and hence the inotify watch becomes invalid (hence only works once)... How can I work around this?

  • 2
    Can you try the utility entr? – Mass May 1 at 23:55
3

Which inotify events are fired depends on how Vim writes the file. This is controlled by multiple options.

In a typical setup it works like this. Assume Vim wants to write the file e.txt

  1. Vim moves the file e.txt to e.txt~
  2. Vim creates a new file e.txt and writes its content

In this case the event MOVE_SELF would be fired. As tools like inotifywait (with -m for "monitor") monitor the file by inode, so it would now in fact monitor the backup file e.txt~.

If Vim writes the same file again, the sequence is like this (note: the backup file already exists):

  1. Vim deletes the backup file e.txt~
  2. Vim moves the file e.txt to e.txt~
  3. Vim creates a new file e.txt and writes its content

So a monitoring inotifywait will receive a DELETE_SELF because the backup file is deleted. Now it listens to changes to an unused inode and will not print anything anymore.

If the file e.txt is in fact a symbolic link to the file tgt.txt, Vim acts different:

  1. Vim copies the content of tgt.txt (the symlinked file) to the backup file e.txt~
  2. Vim writes the content to tgt.txt.

In this case a monitoring inotifywait will see the CLOSE_WRITE (and other) events.

The behavior how Vim saves the file is controlled by the option backupcopy. In nocompatible mode it is set to auto. This means that Vim decides which is the best way to save a file. Hence the two different behaviors described above.

If backupcopy is set to yes, Vim will always create the backup file by copying the original file. In this case inotifywait is able to monitor the file.

If backupcopy is set to no, Vim will always create the backup file by moving the original file. In this case inotifywait is not able to monitor the file. This also has the disadvantage that it will break symbolic links.

See :help 'backupcopy'. This describes the pros and cons of the different values.


So back to inotify: How to monitor a file saved by Vim?

Assuming you want to monitor the file /home/joedoe/e.txt for CLOSE_WRITE events in a shell script:

file=/home/joedoe/e.txt
file_dir="$(dirname "$file")"
inotifywait -mqe close_write --format "%w%f" "$file_dir" |
    while read -r filename; do
        if [ "$filename" = "$file" ]; then
            # do what needs to be done
            ....
        fi
    done

This way you are independent from the strategy Vim uses for saving the file.

| improve this answer | |
0

Found a hint to one solution here:

https://unix.stackexchange.com/questions/188873/using-inotifywait-along-with-vim

:set backupcopy=yes

Seems there may be some risk with this approach though.

| improve this answer | |
  • You actually need to disable backupcopy for that, and the command is set nobackupcopy (not backupcopy=no or something like that...) – filbranden May 1 at 21:37
  • 1
    That gave me an error, maybe cause I'm using neovim? – Chris Stryczynski May 1 at 22:37
  • actually you're correct, it's a string... But it seems to me you need backupcopy=no for the rewrite to happen and trigger inotify. – filbranden May 1 at 23:05
  • One other thing you can do is set an inotify on the directory (not file) and look for rename (move_to) actions there, look for the filename that was moved there and see if it matches the one you were looking for. But it would be really hard to do that with inotifywait, I think you probably need a C or Python etc. tool that would implement that for you... – filbranden May 1 at 23:06
  • @filbranden yes means to copy the file to create a backup and then overwrite the original. So inotify will trigger. no means that the original file is renamed to create a backup and a new file with the original name is created. – Ralf May 1 at 23:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.