Bash script detecting change in files from a directory
You can use inotify-tools definitely from command line, e.g. like this :
inotifywait -r -m /dir/to/monitor/
From man inotifywait
-m
,--monitor
Instead of exiting after receiving a single event, execute indefinitely. The default behavior is to exit after the first event occurs.
And here is a script that monitors continuously, copied from the man file of inotifywait
:
#!/bin/sh
while inotifywait -e modify /var/log/messages; do
if tail -n1 /var/log/messages | grep apache; then
kdialog --msgbox "Blah blah Apache"
fi
done
As others have explained, using inotify
is the better solution. I'll just explain why your script fails. First of all, no matter what language you are programming in, whenever you try to debug something, the first rule is "print all the variables":
$ ls
file1 file2 file3
$ echo $PWD
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*
So, as you can see above, $FILE
is actually expanded to $PWD/*
. Therefore, the loop is only run once on the string /home/terdon/foo/*
and not on each of the files in the directory individually. Then, the md5sum
command becomes:
md5sum /home/terdon/foo/*
In other words, it runs md5sum
on all files in the target directory at once and not on each of them.
The problem is that you are quoting your glob expansion and that stops it from being expanded:
$ echo "*"
*
$ echo *
file1 file2 file3
While variables should almost always be quoted, globs shouldn't since that makes them into strings instead of globs.
What you meant to do is:
for FILE in "${PWD}"/*; do ...
However, there is no reason to use $PWD
here, it's not adding anything useful. The line above is equivalent to:
for FILE in *; do
Also, avoid using CAPITAL letters for shell variables. Those are used for the system-set environmental variables and it is better to keep your own variables in lower case.
With all this in mind, here's a working, improved version of your script:
#!/bin/bash
for file in *
do
sum1="$(md5sum "$file")"
sleep 2
sum2="$(md5sum "$file")"
if [ "$sum1" = "$sum2" ];
then
echo "Identical"
else
echo "Different"
fi
done
You can use the inotify-tools
package to monitor all changes in a folder in real time. For example, it contains the inotifywait
tool, which you could use like :
> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test
You can use flags to filter certain events only or certain files. The inotifywatch
tool collects filesystem usage statistics and outputs counts of each inotify
event.
You can find more examples here for instance.
If you want to monitor with other tools, you can use find
with the -mmin
parameter (modified minutes). Since 2 seconds is like 0.033 minutes, you could use :
find . -type f -mmin 0.033