Reputation: 6051
I'm using this code to get a list of all the files in a specific directory:
opendir DIR, $dir or die "cannot open dir $dir: $!";
my @files= readdir DIR;
closedir DIR;
How can I modify this code or append something to it so that it only looks for text files and only loads the array with the prefix of the filename?
Example directory contents:
.
..
923847.txt
98398523.txt
198.txt
deisi.jpg
oisoifs.gif
lksdjl.exe
Example array contents:
files[0]=923847
files[1]=98398523
files[2]=198
Upvotes: 16
Views: 49990
Reputation: 2089
This is the simplest way I've found (as in human readable) using the glob function:
# Store only TXT-files in the @files array using glob
my @files = grep ( -f ,<*.txt>);
# Write them out
foreach $file (@files) {
print "$file\n";
}
Additionally the "-f" ensures that only actual files (and not directories) are stored in the array.
Upvotes: 3
Reputation: 15988
To get just the ".txt" files, you can use a file test operator (-f : regular file) and a regex.
my @files = grep { -f && /\.txt$/ } readdir $dir;
Otherwise, you can look for just text files, using perl's -T (ascii-text file test operator)
my @files = grep { -T } readdir $dir;
Upvotes: 2
Reputation: 26141
Just use this:
my @files = map {-f && s{\.txt\z}{} ? $_ : ()} readdir DIR;
Upvotes: 1
Reputation: 34130
If you can use the new features of Perl 5.10, this is how I would write it.
use strict;
use warnings;
use 5.10.1;
use autodie; # don't need to check the output of opendir now
my $dir = ".";
{
opendir my($dirhandle), $dir;
for( readdir $dirhandle ){ # sets $_
when(-d $_ ){ next } # skip directories
when(/^[.]/){ next } # skip dot-files
when(/(.+)[.]txt$/){ say "text file: ", $1 }
default{
say "other file: ", $_;
}
}
# $dirhandle is automatically closed here
}
Or if you have very large directories, you could use a while
loop.
{
opendir my($dirhandle), $dir;
while( my $elem = readdir $dirhandle ){
given( $elem ){ # sets $_
when(-d $_ ){ next } # skip directories
when(/^[.]/){ next } # skip dot-files
when(/(.+)[.]txt$/){ say "text file: ", $1 }
default{
say "other file: ", $_;
}
}
}
}
Upvotes: 5
Reputation: 6476
it is enough to change one line:
my @files= map{s/\.[^.]+$//;$_}grep {/\.txt$/} readdir DIR;
Upvotes: 6
Reputation: 90037
my @files = glob "$dir/*.txt";
for (0..$#files){
$files[$_] =~ s/\.txt$//;
}
Upvotes: 12