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

Directory available?

by kingjamesid (Acolyte)
on Oct 19, 2009 at 16:49 UTC ( [id://802029]=perlquestion: print w/replies, xml ) Need Help??

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

I have a dir and sub-dirs underneath it.Inside subdirs, i have files with extension *.mat( and may be some other dirs).

I am performing a recursive fn.

sub readFiles { my $ipath = $_[0]; my $afile; opendir(sDir, $ipath) || die "unable to open sDir: $!"; my @files = grep { /\.mat$/ } readdir(sDir); foreach (@files){ print FILE "$ipath\\$_"."\n"; } closedir(sDir); }
But I need to say, based on a dir (argument to readFiles), check if there is any other dir, if so readFiles again. My question is, what is the command in perl that "checks if there is a directory in a given path). Thanks.

Replies are listed 'Best First'.
Re: Directory available?
by Corion (Patriarch) on Oct 19, 2009 at 16:57 UTC
Re: Directory available?
by ph0enix (Friar) on Oct 20, 2009 at 07:53 UTC

    You can try following code (untested)

    my $separator = ($^O eq 'MSWin') ? '\' : '/'; sub readFiles { my $ipath = shift; my @files; opendir(sDir, $ipath) || die "Unable to open directory '$ipath': $!"; for (readdir(sDir)) { if (!/^\.{1,2}$/ && -d $iPath . $separator . $_) { # recursive call for directory readFiles($iPath . $separator . $_); } else { # collect matching files push @files, $_ if /\.mat$/; } } closedir(sDir); for (@files){ print FILE $ipath, $separator, $_, "\n"; } }
      Thanks

      Notes and Problems:

      • Windows (and DOS and OS/2) accepts a forward slash as path separator, there is no need for $separator. If you want true multi-platform code, use File::Spec, which also handles classic MacOS and more exotic platforms.
      • $^O is never MSWin. It may be MSWin32 or perhaps MSWin64.
      • readFiles() is a bad name, as this function does not read files. It reads directories and print file names found there matching a hardcoded regular expression.
      • The function should really return a list of file names instead of printing them.
      • Recursion is not needed here, you could use a simple worklist (array) instead, containing directories to be processed.
      • Because you use a global directory handle (sDir) instead of a local handle (my $dir) or at least a localized handle (local *sDir), every recursion will automatically close and re-open the handle. Your code only works by accident, because you used for (readdir(sDir)) instead of while (defined($_=readdir(sDir))), reading the entire directory list into memory before iterating over it. Still, each and every call to closedir except for the first one will fail with "Bad file descriptor".
      • There is no need to reinvent directory tree walkers, there are several on CPAN that do not pollute namespaces, that properly check for errors, that work cross-platform, and that do not slurp everything into memory. And, of course, they have parameters allowing to customize the search.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://802029]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-03-28 16:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found