Jay Kim

Gotchas Using fs.watch with Vim

I was debugging an issue with fs.watch Node.js file watcher I was using. I noticed that when the file was edited using Vim, the file watcher could only detect the intial file change and subsequent file changes would not be detected. However when editing using another editor like VSCode, the file changes would be detected.

fs.watch uses inotify in Linux. So to debug this I used the inotifywait command to see what events were being emitted for this file:

jkim@dev-jkim code $ inotifywait --monitor test.txt
Setting up watches.
Watches established.

# First edit
test.txt MOVE_SELF
test.txt ATTRIB
test.txt DELETE_SELF

# Second edit (no output)

For some reason, in the initial edit the file was being deleted. After doing some quick Google searches of 'inotify' and 'vim' I figured out that Vim does the following when you edit a file:

  1. It would move the file test.txt to a test.txt~ presumably for a backup.
  2. It would write the new contents to a new file test.txt.

So this explains why we see MOVE_SELF and DELETE_SELF events and why inotify is unable to see anymore file changes.

It turns out, you can change the behaviour of Vim so that it doesn't create new files for each edit. You can enable the backupcopy setting which forces Vim to overwrite the original file after it makes a copy instead of copying the original file and creating a new file:

set backupcopy=yes

After I set this, the inotify behaves as expected

jkim@dev-jkim code $ inotifywait --monitor test.txt
Setting up watches.
Watches established.

# First edit
test.txt OPEN
test.txt ACCESS
test.txt CLOSE_NOWRITE,CLOSE
test.txt OPEN
test.txt MODIFY
test.txt MODIFY
test.txt ATTRIB
test.txt CLOSE_WRITE,CLOSE
test.txt OPEN
test.txt CLOSE_NOWRITE,CLOSE

# Second edit
test.txt OPEN
test.txt ACCESS
test.txt CLOSE_NOWRITE,CLOSE
test.txt OPEN
test.txt MODIFY
test.txt MODIFY
test.txt ATTRIB
test.txt CLOSE_WRITE,CLOSE
test.txt OPEN
test.txt CLOSE_NOWRITE,CLOSE

It's interesting to note that the problem seems to only occur in non-Unix environments. The help docs for backupcopy state:

'backupcopy' 'bkc' string (Vi default for Unix: "yes", otherwise: "auto")