Reputation: 899
my $directory = shift @_;
my @dh;
my @files;
opendir (my $dh, $directory) or die "Couldn't open dir '$directory' : $!";
foreach my $file(readdir $dh) {
if( -f $file =~ /\.htm$/){
push(@files,$file);
}
elsif(-d $file){
push(@dh,$file);
$dh = shift @dh;
}
closedir ($dh);
}
I am trying to get my script to take in a path e.g. DATA/ (which is successful), however i want my script to scan through that directory and child directories and then if any file matches it will be stored in @files
.
I am trying to use loop to scan through all subfolder e.g.
elsif(-d $file){
push(@dh,$file);
$dh = shift @dh;
}
In this statement $dh
will get a new child directory name to scan through
However i am getting Segmentation fault
Upvotes: 1
Views: 114
Reputation: 126722
There are a few problems here:
readdir
returns the pseudo-directories .
and ..
and these should be ignored
readdir
returns only the file name and not the full path to the file. So -f
and -d
will look in the current working directory for an entry with this name and probably won't find it
You are pushing directory names onto @dh
but shifting directory handles $dh
off it, which isn't going to work
The test -f $file =~ /\.htm$/
first applies the regex to the $file
variable, and then uses the result of that (either 1
or ""
) as a parameter to -f
. That isn't what you want at all
You jump to processing a new directory as soon as you find one, so the rest of the current directory isn't going to be processed
Things like this are normally done using File::Find
or a recursive subroutine, but you can do something like this by eliminiating tail recursion. Note that it takes no account of directory links and can loop endlessly if it finds one. This is why it is best to use a module which has all these kinks ironed out.
use strict;
use warnings;
my @dh = @_;
my @files;
while (@dh) {
my $directory = shift @dh;
opendir my $dh, $directory or die "Couldn't open dir '$directory' : $!";
while (readdir $dh) {
next if /\A\.\.?\z/;
my $node= "$directory/$_";
if (-f $node and /\.html?$/i) {
push @files, $node;
}
elsif (-d $node) {
push @dh, $node;
}
}
}
Upvotes: 3