Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Traversing directories recursively

by jesuashok (Curate)
on Nov 20, 2007 at 09:37 UTC ( #651889=perlquestion: print w/replies, xml ) Need Help??
jesuashok has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,
#!/usr/bin/perl use strict; print_dir ( "." ); sub print_dir { my $dir_name = shift; #print "-->$dir_name\n"; opendir ( my $dir_h , "$dir_name") or die "Unale to open dir :$dir_ +name: $!\n"; #print "Inside Function\n"; while ( my $file = readdir($dir_h) ) { #print "File :$file:\n"; next if ( "$dir_name/$file" =~ /\/\.$/ or "$dir_name/$file" =~ /\ +/\.\.$/ ); #print "$dir_name\n"; #<>; if ( -d "$dir_name/$file" ) { #print "Match\n"; print_dir ( "$dir_name/$file" ); } print "$dir_name/$file\n"; } #return $dir_name; }
I am trying to print the contents of a directory recursively. But I see in the output that the files are printed-out 2 times. Is there anything I am missing out in the recursive function.

i m possible

Replies are listed 'Best First'.
Re: Traversing directories recursively
by grinder (Bishop) on Nov 20, 2007 at 10:15 UTC

    Use the CPAN, Luke.

    #! /usr/bin/perl use strict; use warnings; use File::Find::Rule; my $start = shift || '.'; for my $obj (File::Find::Rule->in($start)) { print "$obj\n"; }

    The key word in the module name is "Rule". You can add rules to restrict what is returned: files only, smaller or larger than a given size, belonging to foo, modified no more than 3 weeks ago, is read-only and so forth.

    Get your rules right, and your own code becomes very simple.

    • another intruder with the mooring in the heart of the Perl

Re: Traversing directories recursively
by andreas1234567 (Vicar) on Nov 20, 2007 at 10:06 UTC
    Works for me:
    $ mkdir foo bar $ touch bar/1 $ touch bar/2 $ touch bar/3 $ touch foo/4 $ touch foo/5 $ touch foo/6 $ mkdir -p bar/tze $ touch bar/tze/7 $ touch bar/tze/8 $ touch bar/tze/9 $ perl -w | sort | uniq -c 1 ./ 1 ./bar 1 ./bar/1 1 ./bar/2 1 ./bar/3 1 ./bar/tze 1 ./bar/tze/7 1 ./bar/tze/8 1 ./bar/tze/9 1 ./foo 1 ./foo/4 1 ./foo/5 1 ./foo/6
    I'd rather use File::Find:
    $ perl -wle 'use strict; use File::Find; find(sub { print if -f }, "." +);' 1 3 2 8 7 9 6 5 4
Re: Traversing directories recursively
by johngg (Abbot) on Nov 20, 2007 at 10:33 UTC
    By choosing a different regex delimiter and using a ? (0 or 1) quantifier you can make this line

    next if ( "$dir_name/$file" =~ /\/\.$/ or "$dir_name/$file" =~ /\/\.\. +$/ );

    simpler and more readable

    next if "$dir_name/$file" =~ m{/\.\.?$};



Re: Traversing directories recursively
by Erez (Priest) on Nov 20, 2007 at 10:16 UTC
    Works for me. I would repeat the usual steps to ease the pain of finding what's not working,
    use warnings as well as strict, use File::Find module instead of writing your own recursion, and some other perlisms.

    Software speaks with tongues of man; I debug, therefore I code.

Re: Traversing directories recursively
by RaduH (Scribe) on Nov 20, 2007 at 20:19 UTC
    Try this:
    sub browse($) { my $path = $_[0]; #append a / if missing if($path !~ /\/$/) { $path .= '/'; } #loop through the files contained in the directory for my $eachFile (glob($path.'*')) { #if the file is a directory if(-d $eachFile) { #browse directory recursively browse($eachFile); } else { your file processing here } } }#browse
    It seems shorter (if you ignore/eliminate the makeup I added to enhance readability) and much simpler than what you have and works. Hope this helps.
      Nice for a programming exercise. But one should should not reinvent the wheel. I'd use something that =~ m/File::Find(?:::Rule)?$/ :-)


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://651889]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (1)
As of 2017-06-27 19:46 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (612 votes). Check out past polls.