tags:

views:

156

answers:

6

I'm looking for a way in Perl to list the plain files of a directory. Files only, no directories.

+1  A: 

You want the readdir operator.

For example:

#! /usr/bin/perl

use warnings;
use strict;

my $dir = "/tmp/foo";
opendir my $dh, $dir
  or die "$0: opendir: $!";

while (defined(my $name = readdir $dh)) {
  next unless -f "$dir/$name";
  print "$name\n";
}

Running it:

$ ls -F /tmp/foo
a  b  c  d/

$ ./prog.pl 
b
c
a

As you can see, the names come out in the order they're stored physically on the filesystem, which isn't necessarily sorted.

To go the quick-and-dirty route, you could also use the glob operator as in

print map { s!^.*/!!; "$_\n" }
      grep !-d $_ =>
      </tmp/foo/*>;

Note that you'll have to remove directories from the result, and the glob operator doesn't return files whose names begin with dots.

Greg Bacon
+10  A: 

You need to use opendir, readdir and closedir functions in conjunction with -f file test operator:

opendir(my $dh, $some_dir) || die $!;
while(my $f = readdir $dh) {
    next unless (-f "$some_dir/$f");
    print "$some_dir/$f\n";
}
closedir $dh;
el.pescado
File::Find is the more general, better answer, in my opinion.
David M
If you don't want to do a depth-first search of an entire tree, File::Find is not the droid you are looking for.
brian d foy
+1  A: 

Use File::Find. It's a core module.

use File::Find;
find(\&wanted, @directories_to_search);
sub wanted 
{ 
   my $file = shift;
   return unless (-f $file);
   #process file
}
Paul Nathan
This is the best answer, as it uses already-written-and-tested libraries. File::Find is in core Perl, so you don't need to install anything.
Ether
Keep in mind that this will recursively list all files in all subdirectories of the specified directory.
toolic
+3  A: 

You can use the file test "operator" (really a function) to check for what sort of file you want.

In the simple case where you want to scan the current directory use a file glob with grep:

my @files = grep -f, <*>;

Otherwise, you can work with a directory handle:

opendir my $dh, $dirpath;

my @files = grep -f, readdir( $dh );

closedir $dh;

See opendir, readdir, closedir, -X, and grep.

daotoad
+4  A: 

Another way to list all files in a directory is to use the read_dir function from the CPAN module File::Slurp:

use strict;
use warnings;
use File::Slurp qw(read_dir);

my $dir = './';
my @files = grep { -f } read_dir($dir);

It performs opendir checks for you. Keep in mind that it includes any "hidden" files (those which begin with a dot). This does not recursively list files in subdirectories of the specified directory.

toolic
+1  A: 

File::Find::Rule from CPAN makes this utterly trivial:

use File::Find::Rule;
my @files = File::Find::Rule->file->in( $directory );

This finds all the files in the given directory or any of its subdirectories. I recommend this because of the combination of extreme flexibility and simplicity.

Joe McMahon