Automatically Run Any File That Changes With watchexec
watchexec is a great little tool for running a specific process when certain files change. For example, I use it to trigger a rebuild of my site when content changes. I also use it to automatically run individual scripts I'm working on with a command like this:
watchexec --project-origin . -w ping.py ./ping.py
That command watches a file named "ping.py" in the current directory and runs it whenever it changes.
It's a bit of a pain to set that up each time. I wrote this bash script to handle automatically running any script in a directory when it changes.
#!/bin/bash
watchexec \
--project-origin . \
--debounce 100 \
--exts .rs \
--exts .py \
--emit-events-to json-stdin \
--fs-events 'modify' \
'jq ".tags[] | select(.kind == \"path\") | .absolute" | xargs bash -c'
Details
-
watchexec is the main process that detects file changes
-
`--project-origin .`` sets up to watch the current directory. It seems like this shouldn't be necessary but I get weird behavior sometimes without it
-
`--debounce 100`` tries to limit the events a little, but it doesn't work the way I expect and sometimes multiple events still show up even with larger values. I'm leaving it here for now as a type of work in progress to dig into more if things become an issue (which hasn't been a problem to date)
-
The `--exts`` arguments set the file extensions the process watches for. Here I'm doing ".rs" and ".py" for my rust and python scripts
-
The `--emit-events-to json-stdin` argument sends notifications out as JSON along STDIN. I use this to find the filepath of the file that changed with `jq`` so I know what to run
-
Using `--fs-events 'modify'`` limits the file events to only when files are modified. Without, lots of extra events for metadata changes show up too
-
The `jq`` command parses the payload from watchexec to grab the path of the file that changed. It's then send to `xargs`` that calls it as an argument to `bash -c`` which results in running the script
Usage
I put that code in script in my one-off script scratchpad directory. Running it lets me work on any of the scripts and seeing them run automatically every time I save changes.