Skip to content

Instantly share code, notes, and snippets.

@someodd
Created October 9, 2025 07:54
Show Gist options
  • Select an option

  • Save someodd/8d8dc5685a5cb7d8bc083d65932642bf to your computer and use it in GitHub Desktop.

Select an option

Save someodd/8d8dc5685a5cb7d8bc083d65932642bf to your computer and use it in GitHub Desktop.
Get notified if a file changes and display the changes.
#!/bin/sh
# feed-diff-ticker.sh — print only the added lines since last snapshot
# Usage:
# feed-diff-ticker.sh /tmp/someodd-feed.txt /tmp/someodd-feed.prev 10 | xrootconsole &
# Env:
# MAX_LINES=100 # optional cap on burst output
# I put this in my crontab:
# curl -s gopher://gopher.someodd.zip:70/0/gateway/status/feed > /tmp/someodd-feed.txt
# I added this to my GNUstep/Library/WindowMaker/autostart:
# /home/tilde/bin/feed-diff-ticker.sh /tmp/someodd-feed.txt /tmp/someodd-feed.prev 10 | xrootconsole &
set -eu
FEED="${1:-/tmp/someodd-feed.txt}"
STATE="${2:-/tmp/someodd-feed.prev}"
INTERVAL="${3:-10}"
MAX_LINES="${MAX_LINES:-}"
WORK_DIR="$(dirname "$STATE")"
TMP_NEW="$WORK_DIR/.feed.new.$$"
TMP_DIF="$WORK_DIR/.feed.diff.$$"
cleanup() { rm -f "$TMP_NEW" "$TMP_DIF" 2>/dev/null || true; }
trap cleanup EXIT INT TERM
# Seed state file if missing
[ -f "$STATE" ] || : > "$STATE"
while :; do
# Skip if feed missing or empty
if [ ! -s "$FEED" ]; then
sleep "$INTERVAL"; continue
fi
# Snapshot current feed (best with atomic mv in cron)
cp -f -- "$FEED" "$TMP_NEW" 2>/dev/null || { sleep "$INTERVAL"; continue; }
# Compute diff; exit codes: 0=same, 1=different, >1=error
if diff -u --label old "$STATE" --label new "$TMP_NEW" >"$TMP_DIF" 2>/dev/null; then
# No differences: do not touch STATE
:
else
# We have differences (exit code 1). Extract ONLY added lines from “new”.
# Strip headers (---/+++), hunks (@@), keep lines starting with '+', then drop the leading '+'.
ADDED="$(sed -n '
1,2d; # drop the first two header lines
/^\+\+\+ /d; # drop +++ header
/^--- /d; # drop --- header (in case)
/^@@/d; # drop hunk markers
s/^\+//p # print added lines with leading + removed
' "$TMP_DIF")"
if [ -n "$ADDED" ]; then
if [ -n "$MAX_LINES" ]; then
printf "%s\n" "$ADDED" | tail -n "$MAX_LINES"
else
printf "%s\n" "$ADDED"
fi
# Update STATE only when we actually emitted new content
mv -f -- "$TMP_NEW" "$STATE"
: > "$TMP_NEW" 2>/dev/null || true
fi
fi
sleep "$INTERVAL"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment