I was looking for a replacement for Haskell’s ghcid to use with Go. This tool made the best first impression.
I’ve used entr quite a bit and have never had to think about it, which is about the highest praise I can offer
My only annoyance is new directories getting added or removed cause it to exit, its easy enough to work around but outside of that one use case its great. My workaround is just use a loop to run it.
Yeah that is listed in the manpage (wrapping in a while loop when using -d) so I think it’s less a workaround and just the expected method (so that you can pipe in the new list of files to watch).
Although that gets painful, because (at least in bash) a while loop doesn’t interrupt well. My workaround is Ctrl-Z followed by kill %1 and fg, but that’s annoying every single time. The only way I’ve found to make it handle nicely is to wrap it in a shell script that traps SIGINT and exits explicitly, but that’s too much baggage.
Tip: Here is the way I approach the loop, a bare while loop isn’t great for reasons you just enumerated, but you can always test the exit of the command is greater than 128 and break out early if so (signals should cause the return code to mask upwards). Something like this is what I do:
while true; do
printf "file\nfoo/file\n" | entr -ad run_command
if [ $? -gt 128 ]; then
note not all utilities/scripts follow proper signal handling but entr does so you’re peachy in this instance, the sleep is there to also be a skosh gentler on the kernel/shell.
Huh, TIL, thanks! Exit codes in relation to signals has always been a bit fuzzy to me. (Did they come out negative in Python?)
Do you happen to know where this is documented?
I was actually trying to fix this by checking the entr exit code, but was further misled by the man page:
The entr utility exits with one of the following values:
0 SIGINT or SIGTERM was received
1 No regular files were provided as input or an error occurred
2 A file was added to a directory and the directory watch option
Won’t show up in the man pages, its a part of the Single Unix Specification/Posix (i think its in WAITPID or one of the c macros around/for wait I forget):
In a nutshell (its complex and different shells behave differently) the return code 0-127 is the low bits of an 8 bit value (can’t be negative its unsigned). When a signal is sent to a process the exit code is 128+signal#, but as an example of “not always” ksh is more 256+128+signal#, bash is even weirder in that it allows for > 8 bit return codes but truncates.
The other caveat with this is if the utility returns an rc > 128 intentionally, you can’t differentiate that from a signal. So caveat emptor. This is all memory of a memory for me at the moment I might be remembering a bit wrong but for stuff like python i’ve seen odd behavior in the return code handling, likely due to missing a signal handler.
Digging further into this, I’m getting properly confused: The while loop above actually interrupts just fine for me, it’s only within a Makefile target that it misbehaves.
Ah that is true, I hadn’t considered that. I usually have it running in a tmux initialisation shell script for anything non-trivial, so I rarely ran into that myself.
I made my own similar tool to learn about inotify, wendy(1), which is a bit more “raw” (you pass a numeric mask to only monitor the events you need). I only discovered entr(1) later on, and I must admit it works pretty well and not only limited to Linux through inotify, which makes pretty useful on BSD.
I’ve used it quite a bit and it works well.
I use entr for so many things, I even use it as a replacement for ghcid when I’m writing Haskell!
I built my own, but entr is more general. Mine is like git ls-files | entr.
git ls-files | entr
Doesn’t have to be a test runner. I use git ls-files | entr make docs to ensure my docs are up to date
git ls-files | entr make docs
I’ve been using this for years! It’s my favorite command line utility.
TIL: Seem to work really nice! Thanks for sharing, this will help to ease my dependence away from using watch as a hammer! It’s also already packaged in Debian which is convenient.
I’ve also used https://github.com/cespare/reflex which works pretty well too. I am not sure if either is “better”.