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

Hi people,

I've encounted a weird problem.Basically, I wanna read entries in a directory and opendir works. However, the readdir just return null strings instead of file names, I'm so confused.

If there are 5 files in $directory, what I got is 7 ''.

Code:

opendir( DIR, $directory ) or die "open dir error"; my $number = 0; while(defined($name = readdir (DIR))) { $number++; if($name eq "") { print "Value -$name* is null string." } print "Loop $number-->$name**\n"; next if $name eq "." || $name eq ".."; next unless $name =~ /(.*)\.lip$/; push @names, $name; }

Replies are listed 'Best First'.
Re: readdir return nul string
by oha (Friar) on Sep 26, 2007 at 10:00 UTC
    I had my bad time copying your code and reformatting it. Please check the Writeup Formatting Tips and fix your layout to be at least readable.

    Your code seems to works fine, readdir returns correct data (neither null?? or undef) and push all the files which ends with '.lip' in the @names array.

    Oha

    Ps: for other monks, i've put the OP code below

    opendir( DIR, $directory ) or die "open dir error"; my $number = 0; while(defined($name = readdir (DIR))) { $number++; if($name eq "") { print "Value -$name* is null string." } print "Loop $number-->$name**\n"; next if $name eq "." || $name eq ".."; next unless $name =~ /(.*)\.lip$/; push @names, $name; }
Re: readdir return nul string
by perlofwisdom (Pilgrim) on Sep 26, 2007 at 11:40 UTC
    Your problem is getting a count of 7 when there are only 5 files, so try moving $number++ AFTER you check to see if the entry is '.' or '..'. Since you're counting BEFORE you get to that logic, you get 7, not 5. If you want to count only the '*.lip' files, move it to after that check.
    opendir( DIR, $directory ) or die "open dir error"; my $number = 0; while(defined($name = readdir (DIR))) { if($name eq "") { print "Value -$name* is null string." } print "Loop $number-->$name**\n"; next if $name eq "." || $name eq ".."; $number++; next unless $name =~ /(.*)\.lip$/; push @names, $name; }
    Thanks oha for the clean version of the code.
      Thank you guys. There is another scenario, if the Perl file is accessed through web(apache http server is started), that is to use http://localhost/test/test.pl, problem will raise. In each loop,the statement $name = readdir (DIR) will get '', instead of filename.However, if run the file as "perl -w test.pl" in linux, everything ok. Could you please gimme some advice on this issue? Thank you.
Re: readdir return nul string
by sankarraman (Acolyte) on Sep 26, 2007 at 13:35 UTC
    Hi,
    for above issue, you can use this code...

    opendir (DIR,dirname); @dir = grep{!/^\.+/} readdir(DIR); closedir(DIR); print join("\n",@dir);

    It will print all the files and the sub directories expect '.' and '..'.
    here i modified your code ...

    opendir( DIR, $directory ) or die "open dir error"; my $number = 0; while(defined($name = readdir (DIR))) { if($name eq "") { print "Value -$name* is null string." } next if ($name eq "." || $name eq ".."); $number++; print "Loop $number-->$name**\n"; # next unless $name =~ /(.*)\.lip$/; push @names, $name; }

    Regards,
    Sankar
Re: readdir return nul string
by Aim9b (Monk) on Sep 26, 2007 at 10:59 UTC
    Here's what I use to get a list if csv files to process...

    chdir $directory; opendir DIR, "." || die "Cannot open $directory directory\n"; # Look for csv filenames... my @csvFiles; while (my $file = readdir DIR ) { if ( $file =~ /.csv$/i ) { chomp($file); push @csvFiles, $file; } # End of if csv file } # End of While closedir DIR;

      Erm, that chomp in there is rather spurious. 99.99% of the time you're not going to have newlines on the end of filenames so it's useless overhead. And the remaining .01% of the time when you actually did have a newline on the end of the filename post-chomp you now no longer have the actual file name in your list.</nit>

      (And you really want or not || in your opendir line.)

        Fletch, thanks for the tips. Can you explain a little further, the whys & wherefores? The examples I used for the open were files, not dirs. Is that the difference. Files use || & dirs use 'or', or is it something else?
        If I'm building a list of files to open, I wouldn't think I would EVER want the newline there. I used the chomp over the chop for just that reason, so I wouldn't lose a significant character of the name.

        Thanks.