Constantly check if file is modified bash
Solution 1
If you have inotify-tools
installed (at least that's the package name on Debian) when you can do something like this:
while inotifywait -q -e modify filename >/dev/null; do
echo "filename is changed"
# do whatever else you need to do
done
This waits for the "modify" event to happen to the file named "filename". When that happens the inotifywait
command outputs filename MODIFY
(which we discard by sending the output to /dev/null) and then terminates, which causes the body of the loop to be entered.
Read the manpage for inotifywait
for more possibilities.
Solution 2
Without inotifywait you can use this little script and a cron job (every minute or so):
#!/usr/bin/env bash
#
# Provides : Check if a file is changed
#
# Limitations : none
# Options : none
# Requirements : bash, md5sum, cut
#
# Modified : 11|07|2014
# Author : ItsMe
# Reply to : n/a in public
#
# Editor : joe
#
#####################################
#
# OK - lets work
#
# what file do we want to monitor?
# I did not include commandline options
# but its easy to catch a command line option
# and replace the defaul given here
file=/foo/bar/nattebums/bla.txt
# path to file's saved md5sum
# I did not spend much effort in naming this file
# if you ahve to test multiple files
# so just use a commandline option and use the given
# file name like: filename=$(basename "$file")
fingerprintfile=/tmp/.bla.md5savefile
# does the file exist?
if [ ! -f $file ]
then
echo "ERROR: $file does not exist - aborting"
exit 1
fi
# create the md5sum from the file to check
filemd5=`md5sum $file | cut -d " " -f1`
# check the md5 and
# show an error when we check an empty file
if [ -z $filemd5 ]
then
echo "The file is empty - aborting"
exit 1
else
# pass silent
:
fi
# do we have allready an saved fingerprint of this file?
if [ -f $fingerprintfile ]
then
# yup - get the saved md5
savedmd5=`cat $fingerprintfile`
# check again if its empty
if [ -z $savedmd5 ]
then
echo "The file is empty - aborting"
exit 1
fi
#compare the saved md5 with the one we have now
if [ "$savedmd5" = "$filemd5" ]
then
# pass silent
:
else
echo "File has been changed"
# this does an beep on your pc speaker (probably)
# you get this character when you do:
# CTRL+V CTRL+G
# this is a bit creepy so you can use the 'beep' command
# of your distro
# or run some command you want to
echo
fi
fi
# save the current md5
# sure you don't have to do this when the file hasn't changed
# but you know I'm lazy and it works...
echo $filemd5 > $fingerprintfile
Solution 3
Came looking for a one-liner on MacOS. Settled on the following. Compiled and added this tool to my path. This took less then 30 seconds.
$ git clone [email protected]:sschober/kqwait.git
$ cd kqwait
$ make
$ mv kqwait ~/bin
$ chmod +x ~/bin/kqwait
Next, I went to the directory in which I wished to do the watching. In this case, I wished to watch a markdown file for changes, and if changed issue a make
.
$ while true; do kqwait doc/my_file.md; make; done
That's it.
Related videos on Youtube
aDoN
Updated on September 18, 2022Comments
-
aDoN over 1 year
I have a file called file1 I want in a script, whenever there is a change in it, do something, a beep sound actually. How do I do that?
-
wurtel over 9 yearsGood point, I hadn't read the manpage that well :-)
-
mr.spuratic over 9 yearsYou don't strictly need
while
. Also note that what a human considers a "modify" might not always work: this will catch an append for example, but it will not catch an editor such asvim
(file watched is renamed or swapped with a backup), norperl -i
(in-place edit) which replaces the file with a new one. Once either of those happens,inotifywait
will never return. Watching an inode and watching a filename aren't quite the same thing, so it depends on the use case. -
wurtel over 9 yearsYou can add other events to wait for, e.g.
move_self
will catch renames. See the manpage for full listing of events. -
muru over 9 yearsUse
diff -q
, ifdiff
supports it. -
Jetchisel over 9 yearsOk let's try that: echo foo > foo.txt; echo bar > bar.txt; diff foo.txt bar.txt --> Files foo and bar differ ## (so much for being quite :))
-
muru over 9 yearsIt is quieter than having every difference spelled out.
-q
means "report if only files differ", not how they differ. Sodiff -q
stops comparing the moment a difference is seen, which can be very useful performance wise. See the GNU documentation, for example. If the whole point of your answer is being efficient by not usingmd5sum
, then not usingdiff -q
if available is defeating that point. -
Jetchisel over 9 yearsOk, -q "performance wise" that is good but it still prints something to stdout/stderr if the file differs from each other. I stated the ! which negate didn't I? what i'm after is the exit status of diff not being 0, ( See the GNU documentation) then take action.
-
muru over 9 yearsYou're missing the point. I have no further desire to explain.
-
rogerdpack over 7 yearsas a note, worked well (if file contents change), appears to be OS X only, and you can install view
brew install kqwait
and you can pass multiple files to it likekqwait **/*
-
rbaleksandar over 6 years
entr
needs to be installed or at least that's the case for Ubuntu. It should be present in most distor repositories out there though. -
AJ Smith 'Smugger' over 2 yearsI think using
stat --format='%Y' $file
be quicker and less resource-intensive (Depending on file size)? Also couldn't using md5sum potentially cause problems if A. The file size is large so would take more time and B. Depending on if the file is currently being written to when the command is called. I feel using stat would be the safer option.