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

I have some code that looks like this:
opendir(MYDIR, $dirname); while (condition) #condition ~ 1, loop basically forever { my @mail = grep { $_ ne '.' and $_ ne '..' } readdir INDIR; foreach (@mail) { # do stuff # delete each file } undef(@mail); # @mail shuld be empty now sleep(1); # give cpu a break } # more stuff... closedir(MYDIR);

The readdir works fine the first time through the loop. All of the files are processed and deleted once processed. Any files that are added to the directory after the first execution of the loop, however, are never found by the readdir command. Do I need to close the directory and reopen it at each iteration (I hope not)? Are the results of readdir cached somewhere perhaps? I looked at the function reference in the Camel book (3rd ed) and didn't notice any gotchas about using readdir in a loop situation. Any ideas?

Guildenstern
Negaterd character class uber alles!

Replies are listed 'Best First'.
Re: Why can't I readdir multiple times in a while loop?
by tye (Sage) on Aug 24, 2000 at 23:03 UTC

    Since this is Win32, you can have the OS notify you whenever a file is added to or deleted from that directory. I haven't used it, but Win32::ChangeNotify sounds like what you'd want to use.

            - tye (but my friends call me "Tye")
      Once again, I must bow to tye. ChangeNotify makes the code ever so better, and I'm not constantly opening and closing the directory unless needed. I bet I looked at the module name a hundred times in the ActiveState help file, but it never clicked in my head to use it.
      BTW, I've posted my code over here. It's certainly not my best piece of code, but it works and hopefully I'll get some good feedback to help on my way to mastery.
Re: Why can't I readdir multiple times in a while loop?
by lhoward (Vicar) on Aug 24, 2000 at 22:24 UTC
    I'm not %100 sure about this, but I suspect that readdir is working like the file read operators. You can't re-read a file from the same handle again until you rewind it. Even if you could, since you're program is trying to "look for new files" you'll probably have to close and re-open the dir handle on each loop. I dont think there is a way to rewind directory handles (you can rewind most filehandles with seek).
      well... there is a rewinddir function. though i've never used it and i'm not sure what it does if the directory gets altered.

      jeff

      Update: apparently there's also a seekdir function. i'd suggest looking into these two functions and see if they'll do what you want them to do.
        Unfortunately, using both rewinddir and seekdir didn't help. Instead of getting nothing the second time through the loop, the array was populated with the values of the files that were previously there and now nonexistent. It may have something to do with the fact that I'm running this on a Win32 platform, I dunno.
        I just moved the opendir and closedir inside the loop, and it works fine now. It makes me feel dirty to have code that opens and closes a directory handle roughly once a second, but it works for now.
Re: Why can't I readdir multiple times in a while loop?
by xdb19 (Sexton) on Aug 24, 2000 at 22:57 UTC
    I am sorry for my previous post, it seems that it does not work as expected, however this code does:
    while (condition) #condition ~ 1, loop basically forever { opendir(MYDIR, $dirname); my @mail = grep { $_ ne '.' and $_ ne '..' } readdir MYDIR; foreach (@mail) { # do stuff # delete each file } undef(@mail); # @mail shuld be empty now closedir(MYDIR); sleep(1); # give cpu a break } # more stuff...

    - Have Fun, XDB19
Re: Why can't I readdir multiple times in a while loop?
by xdb19 (Sexton) on Aug 24, 2000 at 22:51 UTC
    Jeff is right. the rewinddir function is the way to do it. The fixed code looks something like this:

    opendir(MYDIR, $dirname); while (condition) #condition ~ 1, loop basically forever { my @mail = grep { $_ ne '.' and $_ ne '..' } readdir MYDIR; foreach (@mail) { # do stuff # delete each file } undef(@mail); # @mail shuld be empty now rewinddir( MYDIR ); # so rewind the directory sleep(1); # give cpu a break } # more stuff... closedir(MYDIR);

    This code works fine, but you have INDIR instead of MYDIR ( why? ).. either way change
    my @mail = grep { $_ ne '.' and $_ ne '..' } readdir INDIR;
    to
    my @mail = grep { $_ ne '.' and $_ ne '..' } readdir MYDIR;

    - Have Fun, XDB19
      Should have been MYDIR all the way through. Dain bramage in my transposition (didn't feel like cut n paste).
      I tried the rewinddir, but at the next readdir it gave me the names of the files that used to be in the directory, but had been deleted in the previous pass through the loop.
Re: Why can't I readdir multiple times in a while loop?
by Anonymous Monk on Aug 24, 2000 at 23:59 UTC
    Try closing and reopening the directory each time perhaps? It's just a guess, I don't have time to test it.