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

Discussion in 'Perl Misc' started by Peter Juuls, Feb 15, 2006.

  1. Peter Juuls

    Peter Juuls Guest

    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
    Peter Juuls, Feb 15, 2006
    #1
    1. Advertising

  2. Peter Juuls

    Guest

    "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.


    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
    , Feb 15, 2006
    #2
    1. Advertising

  3. Peter Juuls

    Ian Wilson Guest

    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.
    Ian Wilson, Feb 15, 2006
    #3
  4. Peter Juuls

    Paul Lalli Guest

    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
    Paul Lalli, Feb 15, 2006
    #4
  5. Peter Juuls

    Paul Lalli Guest

    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
    Paul Lalli, Feb 15, 2006
    #5
  6. Ian Wilson <> wrote in
    news:dsvoe6$5q8$-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 <>
    (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
    A. Sinan Unur, Feb 15, 2006
    #6
  7. Peter Juuls

    Peter Juuls Guest

    "Peter Juuls" <> wrote in message
    news:43f35bcd$0$46979$...
    > 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
    Peter Juuls, Feb 15, 2006
    #7
  8. Peter Juuls

    Ian Wilson Guest

    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 $!";
    }
    Ian Wilson, Feb 16, 2006
    #8
  9. Peter Juuls

    Ian Wilson Guest

    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.
    Ian Wilson, Feb 16, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steven T. Hatton
    Replies:
    3
    Views:
    9,693
    Pete Becker
    Jun 2, 2005
  2. Patrick Useldinger

    os.stat('<filename>')[stat.ST_INO] on Windows

    Patrick Useldinger, Feb 27, 2005, in forum: Python
    Replies:
    6
    Views:
    1,155
    =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=
    Mar 3, 2005
  3. Magesh
    Replies:
    3
    Views:
    431
    Gordon Burditt
    Oct 5, 2007
  4. Rolf Krüger
    Replies:
    2
    Views:
    607
    Ian Collins
    Mar 12, 2008
  5. ruck
    Replies:
    10
    Views:
    1,258
Loading...

Share This Page