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

Hi! I frequently read from pipes for gzipped data. For example,
open my $fh,"gunzip -c $input_file |" or die "$!";

The trouble is this: if the gunzip returned non-zero (e.g., if the input file does not exist) I don't have a way to detect this. Can you suggest a way to have open fail when the pipe command has non-zero result code? Is this a bash thing, like

set -o pipefail
I can (and do) check for the existence of the input file, but was wondering if there is a better way.

Replies are listed 'Best First'.
Re: detecting non-zero exit code when opening from a pipe
by ikegami (Patriarch) on Oct 21, 2010 at 18:32 UTC

    Full error checking and safer argument handling:

    open(my $fh, '-|', 'gunzip', '-c', '--', $input_file) or die("Can't start gunzip: $!\n"); while (!eof($fh)) { defined($_ = <$fh>) or die("Error reading from gunzip: $!\n"); ... } close($fh) or die("Can't close gunzip: $!\n"); ($? & 0x7F) and die("gunzip died from signal ", ($? & 0x7F), "\n"); ($? >> 8) and die("gunzip exited with error ", ($? >> 8), "\n");

    close

      Hmm... didn't quite trap at the open statement.

      >./errorcheck.pl notexists.gz gzip: notexists.gz: No such file or directory Can't close gunzip:

      I guess the "Can't close gunzip" occurred due to a broken pipe?

        Of course it didn't trap at the open statement. The error hasn't happened yet. As for the incorrect error message, the code should be:

        ... if (!close($fh)) { $! and die("Can't close gunzip: $!\n"); ($? & 0x7F) and die("gunzip died from signal ", ($? & 0x7F), "\n"); ($? >> 8) and die("gunzip exited with error ", ($? >> 8), "\n"); }
        gzip: notexists.gz: No such file or directory gunzip exited with error 1
Re: detecting non-zero exit code when opening from a pipe
by BrowserUk (Patriarch) on Oct 22, 2010 at 00:30 UTC
    Can you suggest a way to have open fail when the pipe command has non-zero result code?

    Simple way (that avoids all the "safer argument handling" bullshit) :

    open my $fh, "gunzip -c $input_file |" and !eof($fh) or die "$!/$?"; while(<$fh>){ ... }

    Elaborate the error handling to suite your needs.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: detecting non-zero exit code when opening from a pipe
by aquarium (Curate) on Oct 21, 2010 at 23:16 UTC
    my two bits worth of pragmatic approach, and something that a complex software i worked on did, is to check the input file is readable, and safely check that the executable exists and is executable. in other words, more checking up front instead of code to pick up the pieces. the code to "pick up the pieces" should exist anyway but for the whole script, in the event of truly unforseen circumstances.
    if the input files have a fleeting existence, or just to be sure, copy it to your own temp file first.
    i'm sure you already considered and discounted the use of the compression/uncompression module, which would get away from using an external executable in the first place.
    the hardest line to type correctly is: stty erase ^H