frogleg has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to do periodic scans for new files in a single directory and process them with a subroutine.
I've written some code, shown below, but it will only process the subroutine once.

I've got two questions for the Monastery:

  1. Why does the subroutine only execute once? I'd like it to run every 30 seconds, hence the do ... while(sleep(30)).
  2. Does anyone have any suggestions on how to modify this script (once working) to process only the new files?

As always, thanks very much.

#!/usr/bin/perl -w use strict; my $dir = "/home/dhaffner/src/codemonkey/test"; opendir (DIR,$dir) or die "That's all folks!"; { do { my @files = grep { -f "$dir/$_" } readdir(DIR); foreach my $file (@files) { GoProcess ($file); } } while (sleep(30)) } closedir (DIR); sub GoProcess { print "I can process $_[0] for you now.\n"; }

Replies are listed 'Best First'.
Re: Help periodically scanning directories to process new files
by merlyn (Sage) on Mar 21, 2001 at 01:48 UTC
    • You're not rewinding your directory handle
    • You're grabbing basenames in @files, not paths, so GoProcess might be confused.
    • Might be better written as an infinite loop:
      while (1) { rewinddir(DIR); foreach my $file (grep -f, map "$dir/$_", readdir DIR) { GoProcess($file); } sleep 30; }
    • Your closedir is never reached. When do you want it to stop?

    -- Randal L. Schwartz, Perl hacker

Re: Help periodically scanning directories to process new files
by Hot Pastrami (Monk) on Mar 21, 2001 at 02:04 UTC
    Here's how I'd do it (untested):
    #!/usr/bin/perl -w use strict; my @files = (); my $dir = "/home/dhaffner/src/codemonkey/test"; my $lastUpdate = 0; LOOP: { opendir(DIR, $dir) or die "Died: $!"; @files = grep { -f "$dir/$_" && (stat "$dir/$_")[9] > $lastUpdate +} readdir(DIR); closedir(DIR); GoProcess("$dir/$_") foreach @files; $lastUpdate = time; sleep 30; redo LOOP; }
    ...but I'm not sure if time() will return the new time, or keep returning the time when the script was first executed. I'll try to find out, and post more in a little while.

    Update: Hmm, well I can't find any info one way or the other. It seems like the camel says that time() returns the time when the script started executing, but I can't remember now, and I haven't got the camel here. Anybody?

    Update 2: The wise arturo says that time() will return the current time, not just the time the script started... so it should work fine.

    Hot Pastrami