in reply to Read directories' contents, add subdirs back into directory list

while i agree that it is probably a good idea to use someone else's wheel, it is often helpful to figure out what's wrong with the round thing you thought you were building. since no-one else spoke of your spokes, i stuck a stick in them myself, and i think i have it.

i think most of your problem is in this section:

a: for(@infiles) { b: $_ =~ s/^(\.|\.\.)$//; c: if (-d $_) {
at line a, you are implicitly setting $_ to items from the directory $dir. in line b, you throw out . and .., and in line c you test to see if $_ is a directory. however, $_ is, in all these cases, relative to $dir -- and perl has no way of knowing that. -d needs the full path or, i believe, the path relative to the location of the script that's running. so here's a quick re-write that will fix this:

#!/usr/bin/perl -w use strict; my @dirs = ( # omit trailing slash '/var/www', '/home/me', '/usr/games', ); for my $dir (@dirs) { opendir DIR, $dir or warn "Error opening $dir:\n$!"; my @infiles = (readdir DIR) or warn "Error reading $dir:\n$!"; closedir DIR or warn "Error closing $dir:\n$!"; for(@infiles) { $_ =~ m/^\.{1,2}$/ and next; my $d = "$dir/$_"; if (-d $d) { push @dirs, $d; next; } # do stuff } } for(@dirs) { print " $_\n"; }

some notes:

first, though this treatment of the array works, i don't like it. manipulating the array you're looping on is vaguely dangerous, just because you get tempted to do much worse things than push onto the end of it. i'd replace that with a while ($dir = shift @dirs), and push $dir onto @keep if you need to keep them for later.

second, you'll note i changed your regex line. i made two changes, both possibly minor stylistic things. one was use of the {1,2} to indicate "one or two" because i find that easier to read than the multiple backslashes and alternation. two, rather than turning those into blank entries and keeping them, if it matched that, i next. why? a little lower, i generate an absolute path by appending the local dirname ($_) onto my current "base" path ($dir), with a slash. if i kept blank ones, this would add the base path back in twice -- infintitely filling the array. ew. bad.

i'd also recommend not using $_; you're naming it explicitly anyway, you might as well give it a real name. but that's totally my own bias, so ignore that.

.

anyway, the moral of the story is "use those other modules" -- but the other lesson is "perl can't guess what you're thinking more than about 90% of the time."

.