The entr Command
You can set commands to run at specific times in Linux, using cron. It’s easy, reliable, and flexible. But what if you need to have commands executed whenever a file changes, or if a new file is added to a directory? That’s possible, too, and there’s more than one way to do it. The entr command is a refreshingly straightforward way to achieve that functionality.
Some systems, such as the Hugo static site generator, have a feature that automatically rebuilds your website if a file changes, or if a new file is added to the site. That little feature makes a significant difference to your workflow. With Hugo, you’re able to have your development version of the website in your browser as you edit the files that make up your site. Each time you save your changes or create a file, the website is rebuilt in milliseconds, and the changes are pushed to your browser. Instant feedback is fantastic.
The entr command brings that type of capability to any set of files. The command that is launched when a change is detected is arbitrary. It can be a standard Linux command, an alias, a shell function, or a script.
Installing entr
To install entr on Ubuntu, use this command:
To install entr on Fedora, type:
On Manjaro, the command is:
A Simple Example
We’ll use the touch command to create a text file called “example.txt” and tell entr to monitor that file.
The entr command accepts the filenames it should monitor via STDIN and accepts the command it should run as command line parameters.
The easiest way to pass a filename to entr is to use ls to list it, and pipe that into entr. When the file changes, entr will launch wc command to count the lines, words, and characters in the file.
The /_ parameter is a placeholder for the filename of the file that was passed to entr. If a group of files is passed to entr, such as *.txt , the /_ parameter would be replaced by the last file to be changed.
Each time the changes are saved to the file, entr launches wc . To stop entr, hit q, or Ctrl+c .
RELATED: What Are stdin, stdout, and stderr on Linux?
Practical Uses
Now that we’ve seen entr in action and you understand the principle, let’s look at some more useful scenarios.
We’ll make entr monitor the files in the current directory. If any of the files are modified, we want entr to launch make for us to rebuild our project. We’ll chain another command, make test, to run some tests on the new build. The AND operator && will only launch the second command if the first completes without any issues.
The -s (shell) option makes sure that the interpreter used is the one defined in the SHELL environment variable. This ensures entr receives the exit code from the first make command.
Using the ls command to send the list of all filenames in the directory to entr is a bit clunky. You might have files in the directory that are part of the project but are not actually build files. Perhaps they are design notes or a to-do list. You don’t need to have your project rebuilt every time you change one of those non-code files.
We can refine the command so that it monitors only the appropriate source code files. This command monitors the C source code and header files.
Of course, we’re not limited to launching make. You might have a custom build script that you’d prefer to use.
Leveraging Git
The entr command isn’t Git-ware, but we can still use some of Git’s capabilities to smooth our workflow.
The git ls-file command will list the files that are in Git’s index and working source tree, taking into account the exceptions that have been defined in your “.gitignore” file. That’s a ready-made list of the files that we’re interested in, so let’s use that as the source of the files to monitor.
The ls-files command accepts command-line options. These can be used to further filter or augment the files list returned by Git:
-c: Show cached files. -d: Show deleted files. -m: Show modified files. -o: Show untracked files.
The –exclude-standard option is a shorthand way to tell Git to ignore files that match the entries in the “.git/info/exclude”, local “.gitignore”, and global “.gitignore” files.
That’ll catch a lot of eventualities, but it won’t cope with a new file being created. And the new file won’t be in Git. We can still cope with that situation, using a little bit of Bash scripting and a feature of entr.
The -d (directory) option causes entr to monitor the files in a directory and to exit if a new file is added. By wrapping our entr command in a while/do loop, the entire entr command line will be automatically restarted, and the new file will be picked up and acted upon. Files and directories whose names start with a period “.” are ignored.
Restarting Servers and Interpreters
Perhaps you work with an interpreted language like Ruby. Each time your program file is changed, you need to stop and restart the Ruby interpreter. You can handle these types of use cases with the -r (restart) option.
To monitor a program file called “hello_world.rb”, and to stop and restart the Ruby interpreter each time the program file changes, use this command:
Each time the program file is edited and saved, the Ruby interpreter is restarted and the program reloaded.
The program initially contained:
It was edited to say:
When this was saved, entr restarted the Ruby interpreter, and reloaded the program.
The file was edited once more to add the word “readers” and saved to the hard drive.
You can see the three outputs in the screenshot. If you press the spacebar, entr will restart the command whether you’ve changed the program file or not.
Not Just for Programmers
Because the command launched by entr can be anything, including shell scripts, the scope for using entr to automate processes is virtually limitless.
Perhaps you have a directory that has files dropped into it by secure FTP, or rsync, or curl. You could have these files automatically copied somewhere else, or compressed, or searched by grep for the word “error”.
This makes it a great tool for system administrators and developers alike.