Watching directories for new files

Linux::Inotify2 is great for detecting newly created files in a directory. You can watch a directory by simply using:

use Linux::Inotify2;

my $inotify = new Linux::Inotify2;

$inotify->watch($dir, IN_CREATE, \&handle_new);

sub watch_new {
my $e = shift;

print "New file or dir: " . $e->fullname . "\n";
}

This will execute the callback function hande_new everytime a file is created in $dir. The function will simply print the new directory or file name created.

Two things interesting, there is no simple way to declare this watcher recursive, but you can add a watch for each directory in a list, for example:

foreach (@dirs) {
    $inotify->watch($_, IN_CREATE, \&handle_new);
}

Or even do something more magical, start by watching every subdirectory, for example:

opendir(DIR, $dir);
while(readdir DIR) {
  -d $_ and $inotify->watch($_, IN_CREATE, \&handle_new);
}
close DIR;

And do this recursively for every directory inside the top directory. Also add a little magic to the callback function:

sub watch_new {
    my $e = shift;

print "New file or dir: " . $e->fullname . "\n";

if (-d $e->fullname) {
$inotify->watch($e->fullname, IN_CREATE, \&handle_new);
}
}

This way you get a watcher for every directory in the top directory, and whenever a new directory is created a new watcher is created for the new directory. This is a simple way to make the watcher "recursive" in real time.

Another interesting tip, imagine that you are watching an upload directory, and people upload files that need to be processed after they are uploaded. Maybe the IN_CREATE event isn't the best one, because it is fired up as soon as the file is create, but in this case you want to wait for the file to finish copying before start processing it. For these situations look at the IN_CLOSE_WRITE event, which is fired up as soon as a file descriptor is closed -- when the file finishs copying.

4 Comments

Wouldn't a more cross-platform solution like File-ChangeNotify (which does Inotify and KQueue) be better?

I am running Perl on several Windows systems.

Does this work on Windows?

This wont work on windows as inotify is a linux kernel feature.

I like the idea of File::ChangeNotify, but unfortunately, it unnecessarily uses Moose instead of something lighter weight like Moo.

Leave a comment

About smash

user-pic I blog about Perl.