Skip to content

Instantly share code, notes, and snippets.

@kch
Last active June 30, 2025 21:18
Show Gist options
  • Save kch/04ccd308e75c43f7ee67e0f5e6ddd494 to your computer and use it in GitHub Desktop.
Save kch/04ccd308e75c43f7ee67e0f5e6ddd494 to your computer and use it in GitHub Desktop.
auto make shebang files executable
[program:fswatch-chmod]
# For each changed file:
# - skips if not regular file
# - skips if no shebang
# - finds enclosing git repo (if any)
# - skips if file tracked and unchanged in that repo (prevent mangling checkouts / rebases)
# - otherwise makes file executable
# - ignore files inside .git but allow in .git/hooks/
command=bash -c '
/opt/homebrew/bin/fswatch -v -r ~/bin ~/src --exclude /\.git/ --include /\.git/hooks/ |
while read file; do
[[ -f "$file" ]] || continue # skip unless is regular file
head -n1 "$file" | grep -q "^#!" || continue # skip unless is shebang
repo=$(git -C "$(dirname "$file")" rev-parse --show-toplevel 2>/dev/null) # repo root
rel="${file#$repo/}" # relative path within repo
[[ -n "$repo" ]] && # is repo
git -C "$repo" ls-files --error-unmatch "$rel" &>/dev/null && # is tracked
git -C "$repo" diff --quiet -- "$rel" &>/dev/null && # is unchanged
continue # skip if in git and tracked and unchanged
chmod +x "$file"
done'
user=kch
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/tmp/fswatch-chmod.log
numprocs=1
stopasgroup=true # Kills whole process group
killasgroup=true # Ensures child processes are killed
startsecs=2 # Wait to ensure stable start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment