There is also a less well utilized fsnotify feature for filesystem-wide notifications. Here is a cross-platform go implementation which also supports OSX: https://github.com/fsnotify/fsnotify
Hey! OP here. I submitted this exactly because I kept running into problems with inotify-tools, and other naive inotify wrappers, where tests would execute multiple times in quick succession, or stop executing on file changes, or other odd behavior.
Entr on the other hand works like a charm. You can see on the website that it details a number of edge cases with inotify that it works around. I'm not even sure it's an exhaustive list.
Note that that particular go implementation is prone to deadlocks.
Also, inotify is suboptimal for this use case. inotify has no recursion support, which means that the user must keep a watch on all files individually. There is also a limit to the number of inotify watches that can be in place at any one time.
A more modern, and more suitable interface for this use case is fanotify[0]. It doesn't provide all the functions that inotify does, but importantly it supports recursion, which alone would seem to make it a more obvious choice for this task.
inofity is no fantastic. Memory use scales with the number of directories watched. The program that uses the inotify system call has to keep a mapping of file descriptors to paths. Inotify is slow, inefficient and error-prone for recursively watching file systems.
fanotify is not an alternative because it cannot monitor file deletion or renames and it requires root permission.
entr is is what I eventually settled on after years of searching the perfect utility to build/run tests after file changes. After using gulp, grunt, watching_testrunner (which I eventually inherited maintainership of), watchman, watchdog (https://github.com/gorakhargosh/watchdog), sniffer (https://github.com/jeffh/sniffer)
entr is cross-platform on OS X, linux and BSD.
watching_testrunner has no BSD support
watchman is way too big and not domain specific enough to my needs
sniffer worked quite well but it required having a scent.py file everywhere
entr keeps it all in a neat, unix like package you can pipe files to.
I keep some example usage in my book, The Tao of tmux at https://leanpub.com/the-tao-of-tmux/read#leanpub-auto-file-w.... In this section I demonstrate my workflow with entr(1) in a Makefile. The code I use in the example should work across OS X / BSD / Linux (note the utilities like find(1) may behave a bit differently across unix-like systems).
I use the Makefile w/ entr(1) in development on my projects like tmuxp at https://github.com/tony/tmuxp/blob/master/Makefile. tmuxp is BSD-licensed so you're free to work off that if you'd like to try it on your own project.
Just a nit: this seems to be imperfect for filenames containing new lines (I know, I know). An xargs like -0, --null option could make it more robust. Then the equivalent of the above command would be something like:
Imperfect as well because any filename starting with a dash will be interpreted as an option to ls.
Nitpicking… or maybe not: if you take the habit of running `cmd * ` whatever the command, I guess you might end up writing dangerous things like `rm * ` in a script which will fatally end up running in a directory containing a file named “-R”.
On the other hand, since the target users are developers, they are in a good position to fix these newline-containing filenames. Even if they are POSIX compliant they shouldn't be encouraged :)
What a coincidence! I tested it yesterday. Worked like a charm. Thanks!
One note: the browser reloading script was not installed on debian, so I downloaded it. It was not clear from the documentation if that was the intention.
> It is not uncommon for modern web frameworks to continuously hunt for file system changes and auto-reloads when run in single threaded or standalone mode. This functionality is superfluous if the application can respond to signals.
This is true if all that happens is a page reload, butamy frameworks are able to patch code or styles into the running page without a reload. This requires more than a signal handler.
Many years ago I did a little utility I called autobuild[0] to do similar things. It has osx and windows support, but never got around doing linux support. I don't think inotify has an easy way of doing recursive filesystem notifications, having to manage the hierarchy and their notifiers, so it lapsed when I didn't need it at the time.
It felt like this kind of tool would/should be one of those standard command line tools always available, or the at least of those standard things everyone knows to install, like silversearcher/ripgrep etc.
this is one of those problems I've needed to solve for forever, but which i've never explicitly looked up a clean solution for. I can immediately think of 3 instances in the past week where this would have been perfect.
We switched from watchman to entr on the project I'm currently working on because watchman was troublesome to configure and IIRC it completely detaches from the shell as well.
A long time entr user, I recently switch to modd for flexible almost makefile like configurability, and watching/ignoring of multiple patterns to name a few convenient feature.
I wrote a dead-simple version of this (that uses polling and doesn't give you filters for files) in python and called it `jonsnow` and threw it on pypi. I understand this is an insanely useful utility, but it's interesting that everyone seems to spin their own :)
https://linux.die.net/man/7/inotify
https://en.wikipedia.org/wiki/Inotify
There is also a less well utilized fsnotify feature for filesystem-wide notifications. Here is a cross-platform go implementation which also supports OSX: https://github.com/fsnotify/fsnotify