r.joseph has asked for the wisdom of the Perl Monks concerning the following question:

I want to find all of a certain type of file in a directory tree (in this case JPEGs) and simply print them. My problem is the recursion through the tree. Here is what I am using:
my $root_dir = '/top/directory/to/start/search'; RunDirs($root_dir); sub RunDirs { my $dir = shift; opendir(TMP_D,"$dir") or die "$! opening $dir"; while(my $tmp = readdir(TMP_D)) { $tmp = "$dir/$tmp"; if ($tmp =~ /\.\.?/) { next; } if (-d $tmp) { RunDirs("$tmp"); } elsif ($tmp =~ /^(\w*)\.(jpg|jpeg)$/) { print "$tmp\n"; } } closedir(TMP_D); }
It works, but it only goes through the first branch, and then stops...for example, say this was a directory structure of mine that I was searching:
-| ROOT -|-| SUB 1 -|-|-| SUB 1.1 -|-|-|-| SUB 1.1.1 -|-|-|-|-| SUB 1.1.1.1 -|-|-|-|-| SUB 1.1.1.2 -|-|-| SUB 2.1 -|-| SUB 2 -|-|-| SUB 2.1 -|-|-| SUB 2.2
The program would only search through the first tree it hits, then stop. In the above example, it would search this and stop:
ROOT -> SUB 1 -> SUB 1.1 -> SUB 1.1.1 -> SUB 1.1.1.1
but it would never get to SUB 1.1.1.2 or SUB 2.1 or SUB 2 or anything, it just stops. I thought that after it had hit the bottom of a certain tree, it would start going back up naturally because of the recursion I used (calling RunDirs multiple times) because the instances of RunDirs() for the higher directories would still be open, and therefore would just grab another entry from readdir(). But obviously, this isn't that is happening? What am I doing wrong - I didn't think directory searching was very difficult, but I guess I am doing something wrong!

Thanks for all the help!
R.Joseph

Replies are listed 'Best First'.
Re: Procesing directories
by Fastolfe (Vicar) on Jan 05, 2001 at 05:34 UTC
    File::Find will do precisely this.
    use File::Find; find(\&wanted, '.'); # execute &wanted for each file descending from + . sub wanted { print $File::Find::name, "\n" if /\.jpe?g$/i; }
Re: Procesing directories
by extremely (Priest) on Jan 05, 2001 at 05:36 UTC
    Two thoughts, the usual why not use File::Find, '-w' and 'use strict;' and aren't you stompling on your directory handler by opening multiples with the same name? You might at least look at DirHandle since that makes you create a new object for each directory handle you open.

    --
    $you = new YOU;
    honk() if $you->love(perl)

Re: Procesing directories
by myocom (Deacon) on Jan 05, 2001 at 05:29 UTC

    Don't re-invent the wheel, use File::Find for this sort of thing. Well worth learning.

Re: Procesing directories
by chipmunk (Parson) on Jan 05, 2001 at 06:49 UTC
    You could "fix" this code by localizing your directory handle: local(*TMP_D);

    But, really, why aren't you using File::Find?

      I think more than localizing the dir handle is needed to get it to work.
      Fastolfe already gave the best answer.
      Now some other trouble with the original code
      if ($tmp =~ /\.\.?/) { next; }
      This will skip any file with one or two periods. This might cause trouble at the mill.
      $tmp = "$dir/$tmp"; if ($tmp =~ /^(\w*)\.(jpg|jpeg)$/)
      \w will only match letters and _. You put a / in.