6

My goal is to run a bash script automatically whenever any new file is added to a particular directory or any subdirectory of that particular directory.

Detail Scenario:

I am creating an automated process for file submission from teachers to students and vice versa. Sender will upload file and it will be stored inside the Uploads directory in the LAMP server in the format, ex. "name_course-name_filename.pdf". I want some method so that when any file stored inside the Uploads folder, the same time a script will be called and send that file to the list of receives. From the database I can find the list of receiver for that particular course and student.

The only concern of mine is, how to call a script automatically and make it work on individual file whenever the content of the directory changes. Cron will do in intervals but not a real time work.

tshepang
  • 12,111
  • 21
  • 91
  • 136
pali
  • 127
  • 2
  • 9
  • 3
    Have you seen [inotify](http://stackoverflow.com/questions/4062806/inotify-how-to-use-it-linux)? – Lars Kotthoff Jun 13 '13 at 11:03
  • ya I have seen it, but, I have never used this and could not find any article describing properly the use of inotify to call abash script – pali Jun 13 '13 at 11:06
  • You can use [inotifywait](http://linux.die.net/man/1/inotifywait) for example. – Lars Kotthoff Jun 13 '13 at 11:09
  • "hek2mgl" has provided a solution for the same... let me check for it . – pali Jun 13 '13 at 11:14
  • I got the solution working provided by "hek2mgl", but its not working inside the subdirectories, please suggest modification to the code provided by "hek2mgl" ... Thnks – pali Jun 13 '13 at 12:04

2 Answers2

4

Linux provides a nice mechanism for that purpose which is called inotify. inotify is mostly available as a C API. But there have been developed shell utilities as well. You should use inotifywait from inotifytools (pkg name in debian) for this. Here comes a basic example:

#!/bin/bash

directory="/tmp"   # or whatever you are interested in

inotifywait -m -e create "$directory" |
while read folder eventlist eventfile
do
    echo "the following events happened in folder $folder:"
    echo "$eventlist $eventfile"
done

Update:

If the problem goes complicated, for example you'll have to monitor recursive, dynamic directory structures, you should have a look at incron It's a cron like daemon which executes scripts on certain events. But the events are file system events rather than timer events.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • I tried your solution. I am getting "Setting up watches. Watches established. " in terminal and the program is not terminating . I am very new to inotify. so please clarify.. – pali Jun 13 '13 at 11:21
  • 1
    Make some changes in the folder an you'll see. :) The program will never terminate in it's current version. It will wait forever for changes. Note that I'll be AFK for a while. Will return back here later. – hek2mgl Jun 13 '13 at 11:24
  • OK, where shall i find the results of inotify , is it inside "directory="/tmp" (i changed tmp according to my need) ?? but i am not getting anything inside that folder !!! – pali Jun 13 '13 at 11:31
  • `inotifywait` produces no output. Refer to the man page that I've linked. You may also google this. I just wanted to point you in the right direction – hek2mgl Jun 13 '13 at 11:35
  • thanks "hek2mgl". your solution works, but it does not work for directories inside the mentioned directory, can you please suggest the solution for the same too, voted for your comment :) – pali Jun 13 '13 at 11:51
  • Yeah, that's true. And it will need some effort to craft a recursive shell script which also respects when new directories will be created or deleted. I've currently done this with PHP. :) You should have a look at [incron](http://inotify.aiken.cz/?section=incron&page=about&lang=en) This might be exactly what you are looking for – hek2mgl Jun 13 '13 at 11:55
  • thanks for incron suggestion, but I am not getting more details about incron, i would like to request you to provide the solution in inotify if its possible for you, voted for your answer :) – pali Jun 13 '13 at 12:02
  • as I said, will be AFK for a while. need to hurry now. Will return later here – hek2mgl Jun 13 '13 at 12:05
  • 2
    Use the `-r` flag with `inotifywait` to watch all subdirectories. Please, read the man page for `inotifywait`. – chepner Jun 13 '13 at 12:38
  • @chepner Thanks for `-r`. I wasn't knowing that. What if a subdirectory will be created in such a folder? will it automatically being watched? (I know I could test this, but have not much time at the moment) – hek2mgl Jun 13 '13 at 14:02
  • Yeah I see!!! :) just had a look there! many thanks! sometimes I don't read the man page because I think I'm already knowing this, but that was wrong in this case :) – hek2mgl Jun 13 '13 at 14:07
  • @chepner Can I ask you what do you think about `incron` ? have you experience with it? I've only heard about sometimes – hek2mgl Jun 13 '13 at 14:15
  • Never heard of it, but sounds promising. – chepner Jun 13 '13 at 14:18
1

There is another option to 'inotifywait':

-d --daemon Same as --monitor, except run in the background logging events to a file that must be specified by --outfile. Implies --syslog.

For completeness:

-m --monitor Instead of exiting after receiving a single event, execute indefinitely. The default behaviour is to exit after the first event occurs.

Within the do-done block of your 'while' statement, you might parse each event report for interesting details then use 'case-esac' to take action based on each event that you care about.

For something that you plan to rely on for your operations, you might also consider replacing the hard-coded '$directory' with some sort of configuration file. Such a file might include the path and filename, the interesting events for that path and file, and a script to run when those events happened. The script might take the list of events as parameters and then 'case-esac' again.

Just one man's ramblins, ~~~ 8d;-Dan

user215881
  • 19
  • 1