Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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 <senko.rasic@dobarkod.hr>
#
# 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
)
@evgenius

This comment has been minimized.

Show comment
Hide comment
@evgenius

evgenius Jul 17, 2013

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

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

@hydranix

This comment has been minimized.

Show comment
Hide comment
@hydranix

hydranix Nov 26, 2013

15 minutes

!/bin/bash

if [ "$1"x = ""x ]; then
cat<<EOF
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]"
EOF
exit 0;
fi
while [ ! -f /tmp/EXITHNx ]; do
sleep 3
inotifywait -r -e create -e delete -e move "${1}" &>/dev/null
XSTA=$?
if [ "$XSTA" = "0" ]; then
eval ${2}
else
touch /tmp/EXITHNx
exit 1
fi
[[ -z ${3} ]] && sleep 150 || sleep ${3}
done
rm -f /tmp/EXITHNx

15 minutes

!/bin/bash

if [ "$1"x = ""x ]; then
cat<<EOF
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]"
EOF
exit 0;
fi
while [ ! -f /tmp/EXITHNx ]; do
sleep 3
inotifywait -r -e create -e delete -e move "${1}" &>/dev/null
XSTA=$?
if [ "$XSTA" = "0" ]; then
eval ${2}
else
touch /tmp/EXITHNx
exit 1
fi
[[ -z ${3} ]] && sleep 150 || sleep ${3}
done
rm -f /tmp/EXITHNx

@ArminVieweg

This comment has been minimized.

Show comment
Hide comment
@ArminVieweg

ArminVieweg Feb 19, 2015

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.

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

This comment has been minimized.

Show comment
Hide comment
@phazei

phazei Apr 7, 2015

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

phazei commented Apr 7, 2015

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

@vn971

This comment has been minimized.

Show comment
Hide comment

vn971 commented Apr 20, 2015

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

@shotputty

This comment has been minimized.

Show comment
Hide comment
@shotputty

shotputty Sep 1, 2015

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?

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

This comment has been minimized.

Show comment
Hide comment
@noscripter

noscripter Dec 9, 2015

why not use watch in homebrew?

brew info watch

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

why not use watch in homebrew?

brew info watch

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

@joshuataylor

This comment has been minimized.

Show comment
Hide comment
@joshuataylor

joshuataylor Jan 5, 2016

Because not everyone runs Mac?

Because not everyone runs Mac?

@hkirsman

This comment has been minimized.

Show comment
Hide comment
@hkirsman

hkirsman Feb 21, 2016

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

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

@Pitt-Pauly

This comment has been minimized.

Show comment
Hide comment
@Pitt-Pauly

Pitt-Pauly Jul 29, 2017

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

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

This comment has been minimized.

Show comment
Hide comment
@mr-moon

mr-moon 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?

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

This comment has been minimized.

Show comment
Hide comment
@tdmalone

tdmalone Mar 12, 2018

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

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

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