I'm looking for a way in Perl to list the plain files of a directory. Files only, no directories.
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.
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;
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
}
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;
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.
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.