0

I am running inotifywait on a directory of files:

inotifywait --quiet --monitor  \
  --event modify \
  --event moved_to \
  --event moved_from \
  --event move \
  --event unmount \
  --event create \
  --format '%w' /path/to/*.json | \
while read FILE; do
  echo "$FILE was changed."
done

This works well until I run git checkout [some existing branch name]. After that, inotifywait stops responding to files that git updated when checking out the branch (That is, is stops responding to files that are different between the two branches).

Why does inotifywait stop responding to these files? Is there a way for it to re-see those files?

J L
  • 400
  • 3
  • 15
  • 2
    Don't point `inotifywait` at the individual files, point it at the *directory*. `git` replaces the files so they no longer exist, so there no longer are any events happening on them. – Charles Duffy Jan 29 '20 at 16:08
  • 1
    Remember that when you get a file handle, it points to an inode, not a directory entry. If you create a new and different file with the same name, it's still a *new and different* file; there's no continuity or relationship. – Charles Duffy Jan 29 '20 at 16:09

1 Answers1

2

inotifywait --event create /path/to/*.json doesn't work at all, because an already-existing file can't have a create event, and /path/to/*.json is replaced with a list of already-existing filenames by your shell before inotifywait is even started; any file that doesn't exist won't be included, and when inotifywait open()s the existing files, it'll get only the preexisting copies, and thus won't even see any new files created under the same name in the future.

Follow the directory instead:

inotifywait --quiet --monitor  \
  --event modify \
  --event moved_to \
  --event moved_from \
  --event move \
  --event unmount \
  --event create \
  --format '%w' /path/to | \
while IFS= read -r file; do
  [[ $file = *.json ]] || continue  # ignore any non-*.json files
  echo "$file was changed."
done

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thank you very much! I ended up using `while read PATH ACTION FILE; do...` along with your approach. I didn't realize about `inotifywait` pointing to an inode; I appreciate your detailed explanation in the comments above, as well as your answer here. I understand `inotifywait` better now, thanks to your explanation. – J L Jan 29 '20 at 19:42
  • Note that the above isn't particularly safe if the file name can contain spaces; better to put it at the end of the input line. (Better than that to use NUL delimiters to allow even names with literal newlines to be correctly handled, but I don't recall whether `inotifywait` supports them). – Charles Duffy Jan 29 '20 at 20:08