mirror of
https://github.com/Brandon-Rozek/website.git
synced 2024-11-09 10:40:34 -05:00
New post
This commit is contained in:
parent
aaa6387b1b
commit
dab1d571f6
1 changed files with 87 additions and 0 deletions
87
content/blog/command-when-file-in-directory-changes.md
Normal file
87
content/blog/command-when-file-in-directory-changes.md
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
---
|
||||||
|
title: "Run a command when a file in a directory changes"
|
||||||
|
date: 2024-01-05T16:00:53-05:00
|
||||||
|
draft: false
|
||||||
|
tags: []
|
||||||
|
math: false
|
||||||
|
medium_enabled: false
|
||||||
|
---
|
||||||
|
|
||||||
|
When editing code or adding content to a HTML file for a website, it can be very useful to see the changes right away after you save the file. We'll show a lightweight way of accomplishing this task with `entr` and a bit of bash scripting.
|
||||||
|
|
||||||
|
First if you don't already have it, install `entr`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf install entr
|
||||||
|
```
|
||||||
|
|
||||||
|
This terminal application works by monitoring files passed within standard in. Therefore, to run a `$command` if any file under some `$directory` changes run the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find $directory -type f | entr $command
|
||||||
|
```
|
||||||
|
|
||||||
|
An example can be running a build script if anything under the source folder changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
find src -type f | entr ./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Now this doesn't capture files that get added to the directory. To do this, we need to get `entr` to monitor the parent folder for any changes. We can do this with the `-d` flag.
|
||||||
|
|
||||||
|
From the man page:
|
||||||
|
|
||||||
|
> **-d** Track the directories of regular files provided as input and exit if
|
||||||
|
> a new file is added.
|
||||||
|
|
||||||
|
Since `entr` exits when a file gets added with this flag, the [common solution](https://superuser.com/a/665208) on the internet is to wrap it in a `while` loop.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ while sleep 0.1 ; do find $directory -type f | entr -d $command ; done
|
||||||
|
```
|
||||||
|
|
||||||
|
This solution works great as a one-liner, but it doesn't let me CTRL-C out when I'm finished. Therefore, I wrote a shell script that incorporates this solution while also adding a `trap`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
show_usage() {
|
||||||
|
echo "Usage: entr-dir [dir] [command]"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check argument count
|
||||||
|
if [ "$#" -lt 2 ]; then
|
||||||
|
show_usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure that the command entr exists
|
||||||
|
if ! command -v entr > /dev/null ; then
|
||||||
|
echo "entr not found. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DIR="$1"; shift
|
||||||
|
|
||||||
|
if [[ ! -d "$DIR" ]]; then
|
||||||
|
echo "First argument must be a directory. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allow for CTRL-C to exit script
|
||||||
|
trap "exit 0;" SIGINT
|
||||||
|
|
||||||
|
while sleep 0.1; do
|
||||||
|
find "$DIR" -type f | entr -d "$@"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
I plopped this in `~/.local/bin/entr-dir`, gave it the `+x` permission, and now I can easily monitor and build projects when files get changed/added/deleted.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
entr-dir src ./build.sh
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in a new issue