f



How to stop perl from exiting when stat($_)->size fails

In my script I fetch the filesize with stat($_)->size from File::stat.
Occasionally it fails although the file exists, and perl exits with this
error on STDERR: Can't call method "size" on an undefined value at
myscript.pl line 7.

I don't want the script to exit, instead I want to ignore the "bad" file and
continue with the next file. I have tried to do tests on file-existence
BEFORE the stat->size is executed, to prevent perl from exiting, but nothing
seems to work.

use File::stat
......
if ((-e $_) && (-r $_) && ($st = stat($_)) {
      $bytes = stat($_)->size ;
}

How can I prevent the script from exiting? (ActiveStatePerl587 on
Windows2000)

Thanks
Best regards
Peter Juuls


0
Peter
2/15/2006 4:50:14 PM
comp.lang.perl.misc 33233 articles. 2 followers. brian (1246) is leader. Post Follow

8 Replies
437 Views

Similar Articles

[PageSpeed] 35

"Peter Juuls" <peter@nospam.com> wrote:
> In my script I fetch the filesize with stat($_)->size from File::stat.
> Occasionally it fails although the file exists, and perl exits with this
> error on STDERR: Can't call method "size" on an undefined value at
> myscript.pl line 7.

If you change it to:
(stat($_) or die $!)->size;
Then at least you will get the real error message.

>
> I don't want the script to exit, instead I want to ignore the "bad" file
> and continue with the next file. I have tried to do tests on
> file-existence BEFORE the stat->size is executed,

You probably have a race condition, where the file exists the first 3 times
you stat it, but not the final time.

> to prevent perl from
> exiting, but nothing seems to work.

If you don't want Perl to exit, don't call the size method on an undefined
value.  The easiest way to do that is to check the definedness of the value
before calling the method.

>
> use File::stat
> .....
> if ((-e $_) && (-r $_) && ($st = stat($_)) {
>       $bytes = stat($_)->size ;
> }


my $st=stat($_);
if (defined $st) {
  $bytes=$st->size;
};


Xho

-- 
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service                        $9.95/Month 30GB
0
xhoster
2/15/2006 5:05:47 PM
Peter Juuls wrote:
> In my script I fetch the filesize with stat($_)->size from File::stat.
> Occasionally it fails although the file exists, and perl exits with this
> error on STDERR: Can't call method "size" on an undefined value at
> myscript.pl line 7.
> 
> I don't want the script to exit, instead I want to ignore the "bad" file and
> continue with the next file. I have tried to do tests on file-existence
> BEFORE the stat->size is executed, to prevent perl from exiting, but nothing
> seems to work.
> 
> use File::stat
> .....

I hope "....." means "use Strict; use Warnings;"

> if ((-e $_) && (-r $_) && ($st = stat($_)) {

perldoc File::Stat says
   $st = stat($file) or die "No $file: $!";
It looks like you are discarding some useful info.

You could simplify this expression by using fewer parens with a lower 
precedence operator and remembering that $_ is a default variable for 
many operators. I'd write something like:
   if ( -e and -r and ... ) {

Though I'm not certain that readability is a prerequisite for 
determinimg the size of a file (is it?)


>       $bytes = stat($_)->size ;

Huh? See perldoc File::Stat for the correct usage!

You might end up with:
   $bytes = $st->size if <expression>;

> }
> 
> How can I prevent the script from exiting? (ActiveStatePerl587 on
> Windows2000)

In general, see
perldoc -f eval


I'd break the expression down into separate statements so that I could 
report failures more fully:
   "file '$_' does not exist!\n"
   "unable to eval stat->size of '$_' because $@"
   etc.

I'm unfamiliar with File::Stat and haven't tested the code quoted above, 
so caveat emptor. Hopefully it will point you in the right direction.
0
Ian
2/15/2006 5:29:45 PM
Ian Wilson wrote:
> Peter Juuls wrote:
> > In my script I fetch the filesize with stat($_)->size from File::stat.
> > Occasionally it fails although the file exists, and perl exits with this
> > error on STDERR: Can't call method "size" on an undefined value at
> > myscript.pl line 7.
> >
> > I don't want the script to exit, instead I want to ignore the "bad" file and
> > continue with the next file. I have tried to do tests on file-existence
> > BEFORE the stat->size is executed, to prevent perl from exiting, but nothing
> > seems to work.
> >
> > use File::stat
> > .....
>
> I hope "....." means "use Strict; use Warnings;"

I don't, since both of those would give compiler errors in Unix, and
silently do nothing in Windows.

> >       $bytes = stat($_)->size ;
>
> Huh? See perldoc File::Stat for the correct usage!

Well, (1) there's no such module, and (2) there's nothing at all wrong
with that usage.  What do you think is wrong with it?

> I'm unfamiliar with File::Stat and haven't tested the code quoted above,

Clearly.  If you had, you wouldn't have chided the OP for perfectly
valid code.  Perhaps you should reconsider that policy in the future.

Paul Lalli

0
Paul
2/15/2006 5:40:43 PM
Peter Juuls wrote:
> In my script I fetch the filesize with stat($_)->size from File::stat.
> Occasionally it fails although the file exists, and perl exits with this
> error on STDERR: Can't call method "size" on an undefined value at
> myscript.pl line 7.
>
> I don't want the script to exit, instead I want to ignore the "bad" file and
> continue with the next file. I have tried to do tests on file-existence
> BEFORE the stat->size is executed, to prevent perl from exiting, but nothing
> seems to work.
>
> use File::stat
> .....
> if ((-e $_) && (-r $_) && ($st = stat($_)) {
>       $bytes = stat($_)->size ;
> }

Why are you mixing the two distinct ways of using stat?

Try one of:

if (-e $_ and -r _ ) {
  $bytes = -s _;
}

or:
use File::stat;
if  ($st = stat($_) and $st->mode & 0400) {
  $bytes = $st->size;
}

> How can I prevent the script from exiting? (ActiveStatePerl587 on
> Windows2000)

In this case, don't call a method on an undefined value - that is,
check the return value of stat() before you try to use that return
value as an object.

In the general case, if you have code that may fail, wrap it in an
eval{} block, and test $@ afterwords.  This is Perl's means of
exception handling.
perldoc -f eval

Paul Lalli

0
Paul
2/15/2006 5:53:24 PM
Ian Wilson <scobloke2@infotop.co.uk> wrote in
news:dsvoe6$5q8$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com: 

> Peter Juuls wrote:
>> In my script I fetch the filesize with stat($_)->size from
>> File::stat. Occasionally it fails although the file exists, and perl
>> exits with this error on STDERR: Can't call method "size" on an
>> undefined value at myscript.pl line 7.
>> 
>> I don't want the script to exit, instead I want to ignore the "bad"
>> file and continue with the next file. I have tried to do tests on
>> file-existence BEFORE the stat->size is executed, to prevent perl
>> from exiting, but nothing seems to work.
>> 
>> use File::stat
>> .....
> 
> I hope "....." means "use Strict; use Warnings;"

use strict;
use warnings;

Case matters.

Sinan

-- 
A. Sinan Unur <1usa@llenroc.ude.invalid>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html

0
A
2/15/2006 9:49:18 PM
"Peter Juuls" <peter@nospam.com> wrote in message 
news:43f35bcd$0$46979$edfadb0f@dread15.news.tele.dk...
> I don't want the script to exit, instead I want to ignore the "bad" file 
> and
> continue with the next file. I have tried to do tests on file-existence
> BEFORE the stat->size is executed, to prevent perl from exiting, but 
> nothing
> seems to work.
>
> How can I prevent the script from exiting? (ActiveStatePerl587 on
> Windows2000)

Thanks for your tips, everyone, I have replaced my old code with this code

use File::stat ;
......
my $st=stat($_);
if (defined $st) {
  $bytes=$st->size;
  };

This is an improvement, the script no longer exits when stat($_) fails for a 
single file. It just skips the "bad" file, and that is what I want.
Still, I don't quite understand why it fails on a valid filename (I DO know 
the file exists and is not accessed in other parts of my script or by other 
programs), it happens seldomly, though, only once for several millions 
files. A tip pointed out that this code gives me the real error message, so 
I will use it to get to the bottom of the problem.

(stat($_) or die $!)->size;


Best regards
Peter Juuls 


0
Peter
2/15/2006 11:56:29 PM
Paul Lalli wrote:
> Ian Wilson wrote:
> 
>>Peter Juuls wrote:
>>
>>>      $st = stat($_); 
>>>      $bytes = stat($_)->size ;
>>
>>Huh? See perldoc File::Stat for the correct usage!
> 
> Well, <snip> there's nothing at all wrong
> with that usage.  What do you think is wrong with it?

I don't see a need to create $st and then throw it away.

 From reading perldoc File::Stat I would use $st when invoking the size 
method.

   my $st = stat($_);
   my $bytes = $st->size;

If you are going to invoke stat($_) twice (needlessly), once as part of 
a conditional and again to obtain the size, then you should just be able 
to do

   if (-e and -r and stat($_)) {
     my $bytes = stat($_)->size;
   }

There's no need to save the results in $st if you never use it.

However the above still looks very 'wrong' to me, it invokes stat twice 
needlessly, invokes -e and -r needlessly and discards all sorts of 
information that I'd want to know about.

I'd do something like

#!/usr/bin/perl
use strict;
use warnings;
use File::stat;

$_ = 't.pl';

if (my $st = stat($_)) {
   print "File $_ has size ", $st->size, " bytes\n";
} else {
   die "Cannot stat($_) because $!";
}
0
Ian
2/16/2006 10:18:09 AM
Ian Wilson wrote:
> Paul Lalli wrote:
> 
>> Ian Wilson wrote:
>>
>>> Peter Juuls wrote:
>>>
>>>>      $st = stat($_);      $bytes = stat($_)->size ;
>>>
>>>
>>> Huh? See perldoc File::Stat for the correct usage!
>>
>>
>> Well, <snip> there's nothing at all wrong
>> with that usage.  What do you think is wrong with it?
> 
> 
> I don't see a need to create $st and then throw it away.
> 
>  From reading perldoc File::Stat I would use $st when invoking the size 
> method.
> 
>   my $st = stat($_);
>   my $bytes = $st->size;
> 
> If you are going to invoke stat($_) twice (needlessly), once as part of 
> a conditional and again to obtain the size, then you should just be able 
> to do
> 
>   if (-e and -r and stat($_)) {
>     my $bytes = stat($_)->size;
>   }
> 
> There's no need to save the results in $st if you never use it.
> 
> However the above still looks very 'wrong' to me, it invokes stat twice 
> needlessly, invokes -e and -r needlessly and discards all sorts of 
> information that I'd want to know about.
> 
> I'd do something like
> 
> #!/usr/bin/perl
> use strict;
> use warnings;
> use File::stat;
> 
> $_ = 't.pl';
> 
> if (my $st = stat($_)) {
>   print "File $_ has size ", $st->size, " bytes\n";
> } else {
>   die "Cannot stat($_) because $!";
> }

I meant warn not die.
0
Ian
2/16/2006 10:31:32 AM
Reply: