Skip to content

Instantly share code, notes, and snippets.

@senko
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
#!/bin/bash
#
# 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 <[email protected]>
#
# 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 onchange.sh
# sudo cp onchange.sh /usr/local/bin
#
# Example use - rsync local changes to the remote server:
#
# onchange.sh rsync -avt . host:/remote/dir
#
# Released to Public Domain. Use it as you like.
#
EVENTS="CREATE,CLOSE_WRITE,DELETE,MODIFY,MOVED_FROM,MOVED_TO"
if [ -z "$1" ]; then
echo "Usage: $0 cmd ..."
exit -1;
fi
inotifywait -e "$EVENTS" -m -r --format '%:e %f' . | (
WAITING="";
while true; do
LINE="";
read -t 1 LINE;
if test -z "$LINE"; then
if test ! -z "$WAITING"; then
echo "CHANGE";
WAITING="";
fi;
else
WAITING=1;
fi;
done) | (
while true; do
read TMP;
echo $@
$@
done
)
@a-r-m-i-n
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.

@phazei
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.

@vn971
Copy link

vn971 commented Apr 20, 2015

The version with eval published by @evgenius https://gist.github.com/evgenius/6019316

@shotputty
Copy link

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

@noscripter
Copy link

why not use watch in homebrew?

brew info watch

source code here:https://gitlab.com/procps-ng/procps

@joshuataylor
Copy link

Because not everyone runs Mac?

@hkirsman
Copy link

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

@Pitt-Pauly
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..

@mr-moon
Copy link

mr-moon commented Nov 4, 2017

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

@tdmalone
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.

@parke
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.

@AVAtarMod
Copy link

Thanks! I modified this script, now it can use entered path, not current directory only =)
Changes there : https://gist.github.com/AVAtarMod/e8bb8ee64cdb009f68d2f70615632b62

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