Skip to content

Instantly share code, notes, and snippets.

Last active July 14, 2023 07:54
Show Gist options
  • Save senko/1154509 to your computer and use it in GitHub Desktop.
Save senko/1154509 to your computer and use it in GitHub Desktop.
OnChange - Watch current directory and execute a command if anything in it changes
# Watch current directory (recursively) for file changes, and execute
# a command when a file or directory is created, modified or deleted.
# Written by: Senko Rasic <>
# Requires Linux, bash and inotifywait (from inotify-tools package).
# To avoid executing the command multiple times when a sequence of
# events happen, the script waits one second after the change - if
# more changes happen, the timeout is extended by a second again.
# Installation:
# chmod a+rx
# sudo cp /usr/local/bin
# Example use - rsync local changes to the remote server:
# rsync -avt . host:/remote/dir
# Released to Public Domain. Use it as you like.
if [ -z "$1" ]; then
echo "Usage: $0 cmd ..."
exit -1;
inotifywait -e "$EVENTS" -m -r --format '%:e %f' . | (
while true; do
read -t 1 LINE;
if test -z "$LINE"; then
if test ! -z "$WAITING"; then
echo "CHANGE";
done) | (
while true; do
read TMP;
echo $@
Copy link

If you change "$@" to "eval $@" you will be able to run several commands.
Example: "rsync dest orig && notify-send Sucess || notify-send Failure"

Copy link

15 minutes


if [ "$1"x = ""x ]; then
Watches for changes recursively, then goes on to execute your command
or script. It wait 2.5 minutes between executes. Good for syncing
directories or doing dynamic backups.
by Hydranix

Usage: DetectChanges "[ directory to watch ]" "[ command/script to execute ]" "[optional: time in second between executes]"
exit 0;
while [ ! -f /tmp/EXITHNx ]; do
sleep 3
inotifywait -r -e create -e delete -e move "${1}" &>/dev/null
if [ "$XSTA" = "0" ]; then
eval ${2}
touch /tmp/EXITHNx
exit 1
[[ -z ${3} ]] && sleep 150 || sleep ${3}
rm -f /tmp/EXITHNx

Copy link

Unfortunately inotifywait does not work with mounted folders. I wanted to use it in my vagrant box, to copy files from eg. /vagrant/www/ to /var/www/ (which is the document root of apache). Mounting files directly to document root slows down php very much, so I thought this would be a nice idea.

Copy link

phazei commented Apr 7, 2015

@ArminVieweg Did you eventually find a solution for that? It's precisely what I was looking to do.

Copy link

vn971 commented Apr 20, 2015

The version with eval published by @evgenius

Copy link

What will be the benefit of running every x minutes (to trigger rsync) versus running rsync every x minutes? Is it just less demanding on the server?

Copy link

why not use watch in homebrew?

brew info watch

source code here:

Copy link

Because not everyone runs Mac?

Copy link

Why can't I kill it with ctrl + c?

Copy link

Nice script! Thanks 👍
I'm using rsync to synchronize my local dir to a remote server's dir, which is working great, but I have to enter my password on every sync. Any ideas on how I could sync fully automatically (without having to enter the password)?
Unfortunately I can't setup an ssh key and use it to authenticate, since the remote is shared and crappy..

Copy link

mr-moon commented Nov 4, 2017

Cool idea, but how would you pass extra arguments with quotes? say i want rsync -a --exclude='folder with space' host:/path?

Copy link

Thanks for the script! I'm having trouble figuring out where the 1 second is defined, as I'd like to extend it.

Copy link

parke commented Sep 28, 2018

@tdmalone, read -t 1 LINE tries to read one line, but with a one second timeout. read is a bash builtin, and is documented on the bash man page.

Copy link

Thanks! I modified this script, now it can use entered path, not current directory only =)
Changes there :

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment