Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

readdir missing one file

by true (Pilgrim)
on Oct 17, 2008 at 15:45 UTC ( [id://717777]=perlquestion: print w/replies, xml ) Need Help??

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

My system admin has me coding on a Redhat Enterprise 5 box. I keep having weird issues with his config and i've been fighting through each one-at-a-time. He knows soo much more than me about Linux, but he doesn't know perl (weird i know). On his machine in Perl 5.6 or perl 5.8 this code:
opendir Tdir, "/path/to/anywhere"; my $dir = readdir(Tdir); while($dir = readdir(Tdir)){ print "$dir\n"; }close Tdir;
outputs folder contents minus one file. Additionally, it also outputs "." and ".." in the array. Every other linux system i've been on usally just outputs the ".." Does anyone know why i am missing a file? SysAdmin tells me i cannot use readdir but i consider it a core function in my code i am really wondering why this is now a problem. Can anyone confirm this error? Anyone have any advice? Thanks for attention,
jtrue

Replies are listed 'Best First'.
Re: readdir missing one file
by kyle (Abbot) on Oct 17, 2008 at 15:51 UTC

    Your first call to readdir goes into "my $dir" and then gets discarded by the next call in the condition of the while loop.

    opendir my $Tdir, "/path/to/anywhere" or die "Can't opendir '/path/to/anywhere': $!"; my $dir; while($dir = readdir($Tdir)){ print "$dir\n"; } closedir $Tdir;
      hmm, i've been using this with no errors for almost a decade. Odd that it never was a problem before. but your are right. This code works:
      opendir Tdir, "/var/www/campbell/campbell.edu/www/content/2/"; while(my $d = readdir(Tdir)){ print "<li>$d\n"; }close Tdir;
      jtrue
        It was a problem before! That's why you never saw the '.' directory; you discarded it. Obviously, in the past you got the files from readdir ordered, with the '.' and '..' directories in front and that's not the case on RH (and shouldn't be depended on).

        Paul

        Sounds like your new version of redhat has a subtle change to the readdir(2) operation (or maybe you changed the filesystem type you were on??). I am pretty sure that, in general, readdir simply returns the entries in the order that they appear in the file. You never used to see "." because it should always be the first entry in the directory file, and your script was discarding it. Now, for some reason, the first entry returned by readdir was not ".", but a file you cared about. Since opendir/readdir say nothing about entry ordering, "it's not a bug -- it's a feature":)
        You still have two bugs and two instances of poor programming.
        • close doesn't work on directory handles. You need closedir .

        • You'll stop iterating prematurely if you have a file named 0 (zero). You need to check if the result of readdir is defined. Check if it's false isn't good enough.

        • Why are you using a global variable for the directory handle?

        • It's so easy to check opendir for errors, it's a very likely candidate for errors. Add a check!

        my $Tdir_qfn = "/var/www/campbell/campbell.edu/www/content/2/"; opendir(my $Tdir_dh, $Tdir_qfn) or die("Can't read dir \"$Tdir_qfn\": $!\n"); while (defined( my $f = readdir($Tdir_dh) )) { print "<li>$f\n"; } closedir($Tdir_dh);
Re: readdir missing one file
by Perlbotics (Archbishop) on Oct 17, 2008 at 16:57 UTC

    Did you check which file is missing, e.g. compare ls -la with your programs output? Is it always the same?

    I checked your program here (SuSE 10.2, perl 5.8.8) and was surprised to see that there was a delta of one file too! Problem was counting the output of ls -la | wc -l vs. perl yourprogram.pl | wc -l. The delta was caused by this line: total 84! Maybe...?

    Update: This works here:

    #!/usr/bin/perl use strict; my %ls = map { chomp; $_ => 2 } qx{/bin/ls -1}; opendir(DIR,".") or die "cannot readdir here - $!"; $ls{$_}++ foreach readdir(DIR); my @where = ("","readir only", "ls only", "both"); foreach (sort keys %ls) { printf("%12s: %s\n", $where[ $ls{$_} ], $_); } __END__ readir only: . readir only: .. both: file1.pl both: file2.pl both: path

Re: readdir missing one file
by ramtek (Novice) on Oct 17, 2008 at 17:19 UTC
    I code on ancient linux boxes all the time :-) What does this return? -M
    $somepath = '/path/to/anywhere'; opendir(DIR, $somepath) or warn "Can't open that directory : $!\n"; @files = ('', readdir(DIR)); foreach $file (@files) { push @keepers, "\"$file\"\n" if ($file ne '' and $file ne '..' and $file ne '.'); } closedir(DIR); print $#keepers + 1 . " files encountered :\n" . join("",@keepers);
    I also always have to filter out ".", ".." and "". I have never NOT had to filter them out. Also check a folder you know you have complete access (maybe one you made) - could be permissions. -M

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://717777]
Approved by kyle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (6)
As of 2024-04-23 15:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found