20

I'm trying to traverse through all the subdirectories of the current directory in Perl, and get data from those files. I'm using grep to get a list of all files and folders in the given directory, but I don't know which of the values returned is a folder name and which is a file with no file extention.

How can I tell the difference?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zain Rizvi
  • 23,586
  • 22
  • 91
  • 133

6 Answers6

33

You can use a -d file test operator to check if something is a directory. Here's some of the commonly useful file test operators

    -e  File exists.
    -z  File has zero size (is empty).
    -s  File has nonzero size (returns size in bytes).
    -f  File is a plain file.
    -d  File is a directory.
    -l  File is a symbolic link.

See perlfunc manual page for more

Also, try using File::Find which can recurse directories for you. Here's a sample which looks for directories....

sub wanted {
     if (-d) { 
         print $File::Find::name." is a directory\n";
     }
}

find(\&wanted, $mydir);
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
21
print "$file is a directory\n" if ( -d $file );
Robert Gamble
  • 106,424
  • 25
  • 145
  • 137
  • 1
    The documentation for all of the file test functions can be found with "perldoc -f -X" (which is pretty unintuitive, I'll admit). – JSBձոգչ Oct 16 '08 at 17:50
10

Look at the -X operators:

perldoc -f -X

For directory traversal, use File::Find, or, if you're not a masochist, use my File::Next module which makes an iterator for you and doesn't require crazy callbacks. In fact, you can have File::Next ONLY return files, and ignore directories.

use File::Next;

my $iterator = File::Next::files( '/tmp' );

while ( defined ( my $file = $iterator->() ) ) {
    print $file, "\n";
}

# Prints...
/tmp/foo.txt
/tmp/bar.pl
/tmp/baz/1
/tmp/baz/2.txt
/tmp/baz/wango/tango/purple.txt

It's at http://metacpan.org/pod/File::Next

szabgab
  • 6,202
  • 11
  • 50
  • 64
Andy Lester
  • 91,102
  • 13
  • 100
  • 152
5
my $dh = opendir(".");
my @entries = grep !/^\.\.?$/, readdir($dh);
closedir $dh;

foreach my $entry (@entries) {
    if(-f $entry) {
        # $entry is a file
    } elsif (-d $entry) {
        # $entry is a directory
    }
}
jonathan-stafford
  • 11,647
  • 1
  • 17
  • 11
5
my @files = grep { -f } @all;
my @dirs = grep { -d } @all;
skiphoppy
  • 97,646
  • 72
  • 174
  • 218
2

It would be easier to use File::Find.

catfood
  • 4,267
  • 5
  • 29
  • 55