14

I am looking write a small bash script to, when launched, watch a directory for any newly created files. If a new file appears, I want its presence to trigger a second script to run.

I see this being used to trigger the compression recently digitized video, and add it to a log of ingested footage.

Currently my code looks like this:

#!/bin/sh

##VIDSTAT is a global variable coming from a parent script.
##proj is the ingestion directory coming from a parent script
proj=$1

dir="/home/$USER/data/movies/$proj"
dirlist=$(ls $dir)


while { $VIDSTAT -eq 1 }:
do
    for mov in $dirlist
    do
        if [ "$(( $(date +"%s") - $(stat -c "%Y" $mov) ))" -lt "5" ]
        then
        ~/bin/compressNlog.sh $mov
        fi
    done
done

Is there an easier/cleaner/less memory intensive way to do this?

EDIT I will be changing the ingestion directory per capture session. I have adjusted the code accordingly

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
Simianspaceman
  • 143
  • 1
  • 1
  • 8
  • 2
    Be careful. The script could run before the application is finished writing the file, and it will compress an incomplete file. – Barmar Feb 04 '13 at 17:51

3 Answers3

19

How about incron? It triggering Commands On File/Directory Changes.

sudo apt-get install incron

Example:

<path> <mask> <command>

Where <path> can be a directory (meaning the directory and/or the files directly in that directory (not files in subdirectories of that directory!) are watched) or a file.

<mask> can be one of the following:

IN_ACCESS           File was accessed (read) (*)
IN_ATTRIB           Metadata changed (permissions, timestamps, extended attributes, etc.) (*)
IN_CLOSE_WRITE      File opened for writing was closed (*)
IN_CLOSE_NOWRITE    File not opened for writing was closed (*)
IN_CREATE           File/directory created in watched directory (*)
IN_DELETE           File/directory deleted from watched directory (*)
IN_DELETE_SELF      Watched file/directory was itself deleted
IN_MODIFY           File was modified (*)
IN_MOVE_SELF        Watched file/directory was itself moved
IN_MOVED_FROM       File moved out of watched directory (*)
IN_MOVED_TO         File moved into watched directory (*)
IN_OPEN             File was opened (*)

<command> is the command that should be run when the event occurs. The following wildards may be used inside the command specification:

$$   dollar sign
$@   watched filesystem path (see above)
$#   event-related file name
$%   event flags (textually)
$&   event flags (numerically)

If you watch a directory, then $@ holds the directory path and $# the file that triggered the event. If you watch a file, then $@ holds the complete path to the file and $# is empty.

Working Example:

$sudo echo spatel > /etc/incron.allow
$sudo echo root > /etc/incron.allow

Start Daemon:

$sudo /etc/init.d/incrond start

Edit incrontab file

$incrontab -e
/home/spatel IN_CLOSE_WRITE touch /tmp/incrontest-$#

Test it

$touch /home/spatel/alpha

Result:

$ls -l /tmp/*alpha*
-rw-r--r-- 1 spatel spatel 0 Feb  4 12:32 /tmp/incrontest-alpha

Notes: In Ubuntu you need to activate inotify at boot time. Please add following line in Grub menu.lst file:

kernel /boot/vmlinuz-2.6.26-1-686 root=/dev/sda1 ro inotify=yes
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Satish
  • 16,544
  • 29
  • 93
  • 149
  • 1
    This Seems like a good solution, though I will be changing the directory per ingestion session. Would it be more efficient to edit the incron tables twice per session, or use a solution that runs as a process and dies afterwards? – Simianspaceman Feb 04 '13 at 18:31
  • I am having some Issues adding entries to the incrontab. It tells me both my user and root "can not use incrontab" – Simianspaceman Feb 04 '13 at 19:48
  • 1
    Create the file /etc/incron.allow (check in etc/incron.conf if that is the right file to allow users), and add root and your user – Satish Feb 04 '13 at 19:53
  • Though this seems like a good solution, It does not seem to work in Ubuntu 12.04 LTS. Though the package installs, and tables are configured... the actions do not trigger a response. – Simianspaceman Feb 05 '13 at 22:03
  • Impossible, it should work on any platform. Must be configuration issue. – Satish Feb 06 '13 at 01:23
  • As part of the below mentioned Inotify, I came across an article that stated in Ubuntu it needed to be explicitly turned on at boot. Might this be necessary? The article referenced an older version of Grub with a menu.lst – Simianspaceman Feb 06 '13 at 15:14
  • 1
    Add following line in Grub menu.lst: kernel /boot/vmlinuz-2.6.26-1-686 root=/dev/sda1 ro inotify=yes – Satish Feb 06 '13 at 16:08
  • that is what it said to do.... but it does not look like that file exists on my machine. If I am not mistaken, Ubuntu 12.04 LTS is using Grub 2, which has a different file set-up than legacy grub versions. Being unfamiliar with editing the boot process where should I being to look for this? – Simianspaceman Feb 06 '13 at 17:11
  • Satish, Thank you so much for all of your help!!!! Actually, I just ran incrond -n; and now that it is no longer daemonized it seems to be working. It seems to be working fine for file manipulation, but it throws errors when I try to have it launch a program with a window (I.e. Totem or VLC in which to play the ingested file for review). Any thoughts on why this might occur and or a workaround? – Simianspaceman Feb 06 '13 at 17:15
  • 1
    so here is the solution for the incron command. VIA [link](http://stackoverflow.com/questions/1584411/how-to-run-an-x-program-from-outside-the-x-session-e-g-from-the-console-or-ssh) `env DISPLAY=:0 XAUTHORITY=/home/brian/.Xauthority _command_`. thanks again for all the help @satish – Simianspaceman Feb 06 '13 at 18:59
7

You can do this with the magical inotify tool :

inotifywait -r -m ./YOUR_MONITORED_DIR |
    while read a b file; do
        [[ $b == *CREATE* ]] && ./another_script "$file"
    done

This method have the big advantage to avoid polling every N seconds.

Inotify (inode notify) is a Linux kernel subsystem that acts to extend filesystems to notice changes to the filesystem, and report those changes to applications. It replaces an earlier facility, dnotify, which had similar goals.

http://en.wikipedia.org/wiki/Inotify
See inotify doc

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
1

Use iwatch. No, really. It'll handle all of the details of making a daemon, running on startup, monitor and log, so on and so on. All you need to do is set the options, and have your bash script handle the details of actually doing something with the file.

Spencer Rathbun
  • 14,510
  • 6
  • 54
  • 73