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

Not sure how to do this in Perl. I print out the contents of a directory (unix) by doing
my $searchpath="/usr/storage"; print "Here are the contents of the chosen search path\n"; sle +ep 2; my @files = <$searchpath/*>; foreach my $file (@files) { print $file . "\n"; }
However if the contents of $searchpath/* is itself a set of sub-directories I wish to print the contents of those as well (displaying the full path for each directory, but not the files within it) down the tree until no more sub-directories exist. I don't won't know the level of recursivness until the code is run.

e.g.

/usr/storage (top level directory) location1 (this is a directory) location2 (this is a directory) afile1 (this is a file) afile2 /usr/storage/location1 afile2 afile3 location3 (this is a directory) /usr/storage/location2 afile /usr/storage/location1/location3 afile afile1 afile2
Any help appreciated .

Replies are listed 'Best First'.
Re: Recursive directory listing
by dHarry (Abbot) on Sep 17, 2010 at 10:09 UTC

    Use File::Find to ease your life (You can tweak it's behavior).

Re: Recursive directory listing
by zentara (Cardinal) on Sep 17, 2010 at 10:23 UTC
    This might be a start for you:
    #!/usr/bin/perl sub get_sub_dirs { my $dir = shift; opendir my $dh, $dir or die "Error: $!"; my @files = grep !/^\.\.?$/, readdir $dh; closedir $dh; for my $file ( @files ) { print "$dir/$file\n"; get_sub_dirs( "$dir/$file" ) if -d "$dir/$file"; } } $topdir= shift || '.'; get_sub_dirs($topdir); exit;

    or

    #!/usr/bin/perl 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($dirH +andle); 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"; } } }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Recursive directory listing
by Khen1950fx (Canon) on Sep 17, 2010 at 11:13 UTC
    I have this set to do both files and directories. To do just directories, then do 'directories-only' => 1 and 'all' => 0. You'll need Filesys::Tree.
    #!/usr/bin/perl use strict; use warnings; use YAML; use YAML::Dumper; use Filesys::Tree qw/tree/; my $tree = tree( { 'all' => 1, 'max-depth' => 10, 'directories-only' => 0, 'full' => 1 }, '/usr/lib' ); my $dumper = YAML::Dumper->new; $dumper->indent_width(1); print $dumper->dump({dump => $tree});
      Thanks for all the replies. Great stuff !
Re: Recursive directory listing
by Generoso (Prior) on Sep 17, 2010 at 14:52 UTC

    You need to use a recursive function like the one below.

    #!D:/Programs/PERL/bin/perl.exe -w use File::stat; my $dir = "D:/"; opendir(DIR, $dir) or die $!; while(defined (my $file = readdir(DIR))) { print "$file\n"; if(-d "$file") { print "directory found....\n"; opendir(newDIR, $file) or die $!; while(defined ($file = readdir(newDIR))) { print "got new file!!!!\n"; print "$file\n"; } closedir(newDIR); } } closedir(DIR);