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
- Vim moves the file
e.txt
to e.txt~
- 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):
- Vim deletes the backup file
e.txt~
- Vim moves the file
e.txt
to e.txt~
- 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:
- Vim copies the content of
tgt.txt
(the symlinked file) to the backup file e.txt~
- 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.