Continuously detect new file(s) with inotify-tools within multiple directories recursively

17

11

I just installed inotify-tools. I would like to continuously detect new file(s) with notify-tools within multiple directories recursively, and send an email using postfix. I can probably handle the send an email using postfix part. I'm just trying to figure out the best way to go about this when trying to detecting new file(s). Because sometimes multiple files are added at once.

David Custer

Posted 2015-08-13T03:36:13.187

Reputation: 373

Answers

39

inotifywait (part of inotify-tools) is the right tool to accomplish your objective, doesn't matter that several files are being created at the same time, it will detect them.

Here a sample script:

#!/bin/sh
MONITORDIR="/path/to/the/dir/to/monitor/"
inotifywait -m -r -e create --format '%w%f' "${MONITORDIR}" | while read NEWFILE
do
        echo "This is the body of your mail" | mailx -s "File ${NEWFILE} has been created" "yourmail@addresshere.tld"
done

inotifywait will use these options.

-m to monitor the dir indefinitely, if you don't use this option, once it has detected a new file the script will end.

-r will monitor files recursively (if there are a lot of dirs/files it could take a while to detect the new created files)

-e create is the option to specify the event to monitor and in your case it should be create to take care about new files

--format '%w%f' will print out the file in the format /complete/path/file.name

"${MONITORDIR}" is the variable containing the path to monitor that we have defined before.

So in the event that a new file is created, inotifywait will detect it and will print the output (/complete/path/file.name) to the pipe and while will assign that output to variable NEWFILE.

Inside the while loop you will see a way to send a mail to your address using the mailx utility that should work fine with your local MTA (in your case, Postfix).

If you want to monitor several directories, inotifywait doesn't allow it but you have two options, create a script for every dir to monitor or create a function inside the script, something like this:

#!/bin/sh
MONITORDIR1="/path/to/the/dir/to/monitor1/"
MONITORDIR2="/path/to/the/dir/to/monitor2/"
MONITORDIRX="/path/to/the/dir/to/monitorx/"    

monitor() {
inotifywait -m -r -e create --format "%f" "$1" | while read NEWFILE
do
        echo "This is the body of your mail" | mailx -s "File ${NEWFILE} has been created" "yourmail@addresshere.tld"
done
}
monitor "$MONITORDIR1" &
monitor "$MONITORDIR2" &
monitor "$MONITORDIRX" &

sahsanu

Posted 2015-08-13T03:36:13.187

Reputation: 991

I forgot to add several explanations regarding the commands used in the sample script thats the reason to edit my answer... I also added the script in case op wants to monitor several dirs. Regarding inotifywait tool, it is impossible to answer the question without mention it because op is using inotify-tools. By the way, I'm a newbie here so I need to learn a lot regarding netiquette, so, sorry if my answer overlaps yours, it wasn't what i want I just want to give a complete answer to op. Again, sorry. – sahsanu – 2015-08-18T13:43:08.253

No problem and welcome to SU. Learning about netiquette is usually done the hard way, as it is not really defined anywhere. – harrymc – 2015-08-18T14:14:59.317

4@sahsanu I do not agree about the whole "netiquette" thing. Each person is answering the question from there own perspective. There is no overlap between answers, nor is there an answer that has been rewritten. It is impossible for the answers to differ in that way when the question is so specific. Thank you very much for taking the time to answer the question in great detail. This has helped more than you know, for someone like me who is just learning about all of this. You have saved me countless hours. – David Custer – 2015-08-18T19:35:50.280

1

@harrymc Netiquetta is defined right here.

– David Custer – 2015-08-18T19:53:29.487

Netiquette in an evolving environment cannot be absolutely defined.It's customary on this site not to duplicate answers unless they are badly written, and even then it's encouraged to correct them instead via editing. It's always your right in a democratic community not to agree. @sahsanu could have avoided my remark by referring to my previous answer while showing his script, which would have gotten your approval in any case. That's what I would have done in his place and that's my netiquette, which I believe I share with others (but not with everyone, of course). – harrymc – 2015-08-18T21:11:20.127

Would I need to call this script from crontab? – a coder – 2016-12-15T14:36:36.373

@acoder no, you should not call it using crontab, well... it depends, if you use the parameter -m it will keep running after it detects the first file created but if you don't use the -m parameter it will end once detects the first file created, I mean, if you use crontab to execute the script every x hours, days, etc, you will get duplicated processes which is not good. You should create a service to start it once your machine is booted or call it manually. – sahsanu – 2016-12-21T17:24:39.433

This only seems to work when I create a directory using linux mkdir. When I create it through file explorer in Windows (this is a network shared drive), it doesn't notice the folder creation at all. Is there a way around this? – frakman1 – 2019-10-31T20:56:46.517

8

Use inotifywait, for example:

inotifywait -m /path -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

For more information and examples see the article
How to use inotify-tools to trigger scripts on filesystem events.

harrymc

Posted 2015-08-13T03:36:13.187

Reputation: 306 093

1If anyone uses this and convert the variables from the read in uppercase, you won't be able to run some commands inside the while.

This is because you would overwrite the $PATH variable. – Savageman – 2015-10-22T15:51:07.047

2@Savageman Using uppercase variable names for your own variables is strongly discouraged precisely for this reason. Uppercase variable names are reserved for system use; your own variables should use lowercase. – tripleee – 2016-03-24T11:40:44.463

@tripleee Thanks for the info, won't use upper-case vars anymore :) – Savageman – 2016-03-24T16:05:46.900

0

For several directories you can do this:

#!/bin/bash


monitor() {
  inotifywait -m -r -e attrib --format "%w%f" --fromfile /etc/default/inotifywait | while read NEWFILE
  do
     echo "This is the body of your mail" | mailx -s "File ${NEWFILE} has been created" "yourmail@addresshere.tld"
  done
          }


monitor &

Here is an example list of folders in the file /etc/default/inotifywait /etc/default/inotifywait

/home/user1
/path/to/folder2/
/some/path/

Konstantin Frank

Posted 2015-08-13T03:36:13.187

Reputation: 1