perlstatfile-find

File::stat returns "No such file or directory"


When I run this program:

#!/usr/bin/perl -w

use File::Find;
use File::stat;
use Time::gmtime;
use Fcntl ':mode';

my %size = ();
my @directory = ('.');

find(
    sub {
        my $st = stat($File::Find::name) or die "stat failed for $File::Find::name : $!";
        if ( defined $st )
        {
            my $gm = gmtime $st->mtime;
            $size{$gm->year + 1900} += $st->blksize unless S_ISDIR($st->mode);
        }
        else
        {
            print "stat failed for ", $File::Find::name, ": $!\n";
        }
    },
    @directory);

foreach my $year (keys %size)
{
    print "$year ", $size{$year}, "\n";
}

I get stat failed for ./1128/00 : No such file or directory at ./size.pl line 13.. But, when I list it, it's there:

# ls ./1128/00
03  05  07  09  12  14  18  20  22  24  27  29  32  34  37  40  43  45  47  50  52  54 57  59  63  65  67  69  75  78  81  83  85  88  90  92  95
04  06  08  11  13  15  19  21  23  25  28  31  33  35  39  41  44  46  48  51  53  55  58  61  64  66  68  71  77  79  82  84  86  89  91  93

Based on diagnostics that I have removed for this question, I can see that it does successfully stat the first 4 files and the . directory and 1128 directory (parent to 1128/00). It always successfully stats the same files and directories and fails on 1128/00. Why is it failing?


Solution

  • By default, File::Find will chdir to each directory as it recurses.

    Because of this, performing stat on the $File::Find::name value of ./1128/00 is actually looking for the file ./1128/./1128/00, which does not exist.

    To get the behavior that you want, simply perform your file operations on the $_ variable.

    my $st = stat($_) or die "stat failed for $_: $!";