Lamont85 has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

The following script is meant to iterate through all files within a directory, including subdirectories. It seemed the solution would be easy. Unfortunately, this spits out something about an invalid dirhandle at line 18 (marked with ***).

#!C:\Perl64\bin\perl.exe use strict; use warnings; my $remoteaddr = "//192.168.25.2/"; my %directories = ( media => $remoteaddr . "Media", software => $remoteaddr . "Software" ); sub getdir { my $dir = shift; opendir (my $dh, $dir) || die qq(Cannot opendir: $dir); while( my $file = readdir($dh)) { #********************************* +***** next if ($file =~ m[^\.{1,2}$]); # Ignore . and .. my $path = $dir .'/'. $file; if (-e $path) { # do some stuff } elsif (-d $path) { getdir($path); } closedir ($dh); } } foreach my $directory (keys %directories) { getdir($directories{$directory}); }

Any help would be appreciated.

-cory-

Replies are listed 'Best First'.
Re: Bad file descriptor error
by jethro (Monsignor) on Mar 22, 2010 at 10:06 UTC

    you are closing the dirhandle IN the loop instead of after it. Just move the 'closedir' line after the following '}'

    This is an example why it is better to use well-tested library code instead of redoing the same tasks over and over again. Take a look at File::Find, it might make your task easier next time.

      It is also an example where consistent indentation would have helped to spot the problem, as well as wider indentation of 4 spaces instead of 2 and comments:
      sub getdir { my $dir = shift; # Open the directory handle, reporting the reason ($!) opendir (my $dh, $dir) || die qq(Cannot opendir: $dir: $!); while( my $file = readdir($dh)) { next if ($file =~ m[^\.{1,2}$]); # Ignore . and .. my $path = $dir .'/'. $file; if (-e $path) { # do some stuff } elsif (-d $path) { getdir($path); } closedir ($dh); # Close the directory handle - OOPS } }
        The 4 spaces look much better.

        But the comments you proposed don't add anything of value. "open the directory handle ..." is as easy or difficult to understand as "opendir(...) or ...". Even more obvious with the closedir line, the comment is just redundant noise.

        Comments should add information not repeat it IMHO. A good place for comments is at the start of a subroutine, to exactly specify what parameters are expected and what is returned. Or at really complicated lines to sum up what is done there

Re: Bad file descriptor error
by thillai_selvan (Initiate) on Mar 22, 2010 at 10:01 UTC
    Here you are matching the regular expression using 'm' is not enclosed properly. Please correct it as follows if ($file =~ m/^\.{1,2}$/) # Ignore . and ..