Skip to content

Instantly share code, notes, and snippets.

@elfsternberg
Created November 15, 2025 22:13
Show Gist options
  • Select an option

  • Save elfsternberg/bf97f6cf31edaa50d5c9c9717bc82945 to your computer and use it in GitHub Desktop.

Select an option

Save elfsternberg/bf97f6cf31edaa50d5c9c9717bc82945 to your computer and use it in GitHub Desktop.
swatch-cats: A simple monitor to watch the webcam watching my cats
#!/usr/bin/env bash
# Absolutely dumb progressive "screensaver". Basically, it watches a folder and, whenever a new
# image appears, puts that one up fullscreen, then tears down the prior one underneath. Useful for a
# folder where you're monitoring a webcam and want to check the results
# Requires [feh](https://feh.finalrewind.org/),
# inotifywait(https://github.com/inotify-tools/inotify-tools).
echo "$$" > $HOME/.swatch-pid
set -o errexit
set -o nounset
shopt -s nullglob
function _die() {
echo "ERROR $? IN ${BASH_SOURCE[0]} AT LINE ${BASH_LINENO[0]}" 1>&2
exit 1
}
trap _die ERR
PID=""
ZOOM="${SWATCH_ZOOM:---auto-zoom}"
# Disabling because shellcheck has no good answer for "ls -t"
# shellcheck disable=SC2012
LATEST=$(ls cats-*.webp | grep -v '^feh_' | tail -1)
if [ -n "$LATEST" ]; then
feh --fullscreen --draw-filename $ZOOM --start-at "$LATEST" $(ls cats-*.webp | grep -v '^feh_') &
PID="$!"
fi
lastfile="-nofileyet-";
inotifywait -m . -e close_write --include '\.webp' |
while read -r _path _action file; do
if [[ "$file" == cats-* ]] && [[ "$file" != "$lastfile" ]]; then
# Needed because create can be triggered before the file is completely coherent. Probably
# not the best way, but haven't seen in glitch yet.
sleep 2
echo "Update: $file"
feh --fullscreen --draw-filename $ZOOM --start-at "$file" $(ls [0-9]*.webp | grep -v '^feh_') &
lastfile="$file"
NPID="$!"
if [ -n "$PID" ]; then
if ps --pid "$PID" > /dev/null; then
# This delay prevents a flash as the prior process gets killed faster than X can set
# up the view for the new image.
sleep 1
kill $PID
fi
fi
PID="$NPID"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment