views:

44

answers:

2

Hi, 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: http://i.imgur.com/RMmFz.jpg

Hope someone can help and thanks very much for your time. :)

+1  A: 

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.

martin clayton
Thanks heaps :D. For all those reading this in the future, the solution is to change this: "if (-f $file)" to this: "if (-f "$dir$file")"
Aaron
+1  A: 

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"; 
toolic
Thanks toolic! :D I'll have to do a few more tutorials before I understand all of this.
Aaron