Aaron
Aaron

Reputation: 31

Win32 Perl - Telling the difference between files and folders using a passed directory argument

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

Answers (2)

martin clayton
martin clayton

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

toolic
toolic

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

Related Questions