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

Hi. I've this:
open (INFILE, $inputFile) || die "analysis file not found";
but I'm going through a directory containing 1000s of files. I don't want it to die but print a msg instead and continue. I looked in perlfaq but there was nothing there. Thank you.

Replies are listed 'Best First'.
Re: how to prevent open from dying
by ikegami (Patriarch) on Jun 30, 2006 at 15:19 UTC

    if, warn and next

    while (...) { local *INFILE; if (!open(INFILE, '<', $inputFile)) { warn("Unable to open analysis file $inputFile: $!\n"); next; # } ... }
    • Your error message was wrong. Don't assume it's because the file was not found. open sets $!, so use it. Also, it would be useful to specify the file for which the error occured.
    • I used the 3-arg open for safety.
    • Don't forget to limit the scope of your file handles (as done here using local).

      Don't forget to limit the scope of your file handles .. or just use lexicals:

      while ( ... ) { open my $fh, '<', $inputFile or warn( "Unable to open analysis file $inputFile: $!\n" ); next unless defined $fh ... }

      -derby
        I hate testing for the same condition twice in a row, as you did.
        while ( ... ) { my $fh; if (!open($fh, '<', $inputFile)) { warn( "Unable to open analysis file $inputFile: $!\n" ); next; } ... }

      Why not use lexical filehandles too? :-)

      - yes, I'll use $! instead
      - can you explain the "3arg" deal? So nothing can be slipped in the file name? Like "; cat /etc/passwd" or smth?
      - what's the point of limiting file handles??
      Anyway, thank you all for your replies.

        The open with 3 args seperate special characters from the filename, allowing you to access files you couldn't access before, and preventing the unintended creation, destruction and execution of other files.

        Limiting the scope of all variables (not just file handles) is a great practice. It frees resources earlier. It limits the number of things the programmer and the maintainer must track. It prevents bugs and the maintainability nightmares of having a variable server multiple purposes. etc.

Re: how to prevent open from dying
by Zaxo (Archbishop) on Jun 30, 2006 at 15:20 UTC

    Replace die with warn:

    open INFILE, '<', $inputFile or warn("analysis file not found"), next;

    After Compline,
    Zaxo

      I guess the only problem with this snipped is that it prints nothing to stdout. It just blows right through missing files and keeps going.

        It prints to STDERR, just like die does.

        After Compline,
        Zaxo

Re: how to prevent open from dying
by blue_cowdawg (Monsignor) on Jun 30, 2006 at 15:20 UTC
        . I don't want it to die but print a msg instead and continue.

    Try something like:

    open(FILE,"< some_darn_file_or_another") or do_something_else_besides_die(); | } sub do_something_else_besides_die { printf "Belch!\n"; }
    The call to die that you are referring to is not mandatory. You can execute whatever code you want after the or.

    Now, the real issue is you need to do some sort of error recovery upon a failed open such that you aren't trying to read/write to an unopened file handle.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: how to prevent open from dying
by chromatic (Archbishop) on Jun 30, 2006 at 15:21 UTC

    If you have the source code for this program, you could look for the Perl command that causes Perl to die and change it to the Perl command that causes Perl to print something.

    I suspect I may be missing the point of your question though. Are you asking how to handle the exceptional condition? Then look at the documentation for eval. (From the command line, perldoc -f eval or perldoc -f die may help you. Otherwise, you can find perlfunc.pod online in many places.

Re: how to prevent open from dying
by radiantmatrix (Parson) on Jun 30, 2006 at 18:58 UTC

    I suspect that code is followed by one or more I/O operations on that file, and you certainly don't want to attempt those operations if the file isn't open. So, while you can simply replace die with warn or print (or any other statement), what you probably want to do is simple exception handling.

    Something like this ought to do:

    use strict; use warnings; #always a good idea! #... some loop that sets $inputFile to the file path ... eval { # try to open the file, die and explain the problem on failure open my $INFILE, '<', $inputFile or die "Cannot read '$inputFile': +$!" #.. do I/O on $INFILE (e.g. <$INFILE>, [doc://sysread], etc.) ..# }; if ($@) { # this catches the message from any "die" in the eval{} block # the message will be in the scalar '$@'; print "!: Error while working on file-> $@" } #.. move on to the next file ..#

    With this style of code, any operation inside the eval that causes a die (like an error while reading) will terminate only the eval block and set $@ to be the message from die. You can then handle this message appropriately and move on to the next file.

    This is similar in spirit to Java's try{ } catch{} syntax.

    <radiant.matrix>
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet
Re: how to prevent open from dying
by mikasue (Friar) on Jun 30, 2006 at 15:21 UTC
    What do you want the message to say? Which file failed?