in reply to Builing a Recursive Directory Listing

Here's the NON CPAN-module-using version. I had a highschool project waaay back when that required a similar thing (finding file dupes with crc's). It's simple and a quick one with a few inline critiques.. but you get the idea :)

use strict; use warnings; my $level = 0; processDir("."); ### # Possibly add a callback so that it doesn't only print # directories but can do other stuff too. ### sub processDir { my ($curDir) = @_; my $dirHandle = undef; opendir($dirHandle, "$curDir"); ### # Didn't feel like playing w/ regexps for a quick solution ### my @contents = sort grep { $_ ne "." and $_ ne ".." } readdir($dir +Handle); closedir($dirHandle); foreach my $file (@contents) { print "\t" x $level; print "$file"; if( -d "$curDir/$file" ) { print "/\n"; ### # Dont' follow symlinks... they cause loops ### if( ! ( -l "$curDir/$file" ) ) { ### # I should pass the level along or make it all # iterative. But you get the idea ### $level++; processDir( "$curDir/$file" ); $level--; } } else { print "\n"; } } }

p.s. use cpan modules, they are proven. this is just to show you what you asked for in native code. I wouldn't be surprised if the Find::* utils didn't do something similiar w/o recursion.. but that wasn't the point :)

Update: Grinder thought it didn't check symlinks when I was. Added a comment where the check is, + fix the -l test to actually work. On my machine, opendir() of a symlink doesn't work, but I won't say it won't on another machine. :)


Play that funky music white boy..

Replies are listed 'Best First'.
Re:x2 Builing a Recursive Directory Listing (beware of loops)
by grinder (Bishop) on Dec 15, 2003 at 13:42 UTC

    This approach is frowned upon in the general case, because if you follow symbolic links. If a chain of symbolic links ever gets back to above where you are in the the directory tree, you will have created a loop, and your program will never terminate.

    update: Duh! I skimmed too much and missed the -l test. Sorry sporty, bad me. I guess after having seen half a dozen wrong solutions posted here over the years one starts to expect them to be all wrong. Which by extension is another reason to use File::Find, it offers a much higher level of conceptual chunking.

    It might be something as simple as foo -> ../../../ but it might also be something more subtle: foo -> /bar/new/foo and something in /bar/new/foo points back here again. In my experience it's always1 been something fairly obscure, always involving new versions of applications and new disks being added to the machine. After a few years, this sort of cruft builds up and makes the scenario inevitable.

    The File::Find modules take care this problem into account, and can thereby save you from shooting yourself in the foot.

    Maybe I should point out that I'm not pointing the bone at sporty, but rather warning those who'll see this in the future and think that this would be a better approach than to use standard modules, NIH syndrome and all that.


    1. Always... well, this did happen to me once, a long time ago. It was a lesson learnt, and now I use File::Find.
      Actually, that's why the ! ( -l $file ) test is there.. so it doesn't. I should change this to $curDir/$file, which i'll update it to be :)

      I suggest you reread the code i posted. :) The test was there, it just wasn't written 'well'

      Update: I thought I said using the CPAN module was preferred and stuff. Guess I dreamed that :)


      Play that funky music white boy..
Re: Re: Builing a Recursive Directory Listing
by revdiablo (Prior) on Dec 15, 2003 at 17:18 UTC

    I haven't looked through your code, but I just wanted to comment on your, er, comment about being "NON CPAN-module-using". You might note that File::Find is a core module (you can find the list of these in your perlmodlib perldoc). CPAN is not required to get it -- it is almost certainly included with your copy of perl itself. This is usually the thing to use, unless there is something very specific that this code does that File::Find does not. (Again, there might be, as I haven't looked at your code. But I'd be shocked if it couldn't be done with File::Find.)

    Please don't take this as a personal attack against you or your code. I noticed File::Find mentioned as a "CPAN module" in another note as well, so I figured the matter might use some clarification.

      You are 100% right about being able to do it w/ file find. I didn't know it was NOT cpan. Tnx for the clarification.

      I hope no one would use my code :) Being the CS person that I am, I like to explain what is going on that assuming that everyone else already doesn't. It's one of my favourite things... programemrs who think they know how things work, but really don't :)


      Play that funky music white boy..