Reputation: 31
I'm writing a script in perl strawberry. The first thing it needs to be able to do is take a path argument and get a directory listing for that path, and it needs to be able to distinguish between files and folders. I read some tutorials on the subject and wrote the script below, but it only works when I give it the path that the script is currently residing in. If I give it any other path, the -f and -d tests don't work.
EDIT: Clarification: The script DOES put all the files and folders into @thefiles if I give it a path other than it's own, it's just the -f and -d tests that don't work.
use Getopt::Long;
my $dir;
GetOptions('-d=s' => \$dir);
opendir(DIR, $dir) or die "BORKED";
@thefiles = readdir(DIR);
print DIR;
closedir(DIR);
@filez;
@dirz;
foreach $file (@thefiles){
if (-f$file){
push(@filez, $file);
}
if (-d$file){
push(@dirz, $file);
}
}
print "files: @filez \n";
print "Directories: @dirz \n";
Here's a screenshot: https://i.sstatic.net/RMmFz.jpg
Hope someone can help and thanks very much for your time. :)
Upvotes: 3
Views: 663
Reputation: 78135
It's because the filetest -f
and -d
operators use a relative path unless you provide an absolute one. The readdir
function will return the file (and subdirectory...) names found in the directory, but not the full paths.
From the docs:
If you're planning to filetest the return values out of a readdir, you'd better prepend the directory in question. Otherwise, because we didn't chdir there, it would have been testing the wrong file.
Upvotes: 1
Reputation: 62083
martin clayton told you the reason your code does not work.
Here is a way to fix it using map and some more modern Perl constructs:
use strict;
use warnings;
use Getopt::Long;
my $dir;
GetOptions('-d=s' => \$dir);
opendir my $dh, $dir or die "BORKED: $!";
my @thefiles = map { "$dir/$_" } readdir $dh;
closedir $dh;
my @filez;
my @dirz;
for my $file (@thefiles) {
push @filez, $file if -f $file;
push @dirz , $file if -d $file;
}
print "files: @filez \n";
print "Directories: @dirz \n";
Upvotes: 1