How can I check if a filehandle is open in Perl?

61

Solution 1

Please see the answer regarding openhandle() from Scalar::Util. The answer I originally wrote here was once the best we could do, but it's now badly outdated.

Solution 2

The Scalar::Util module provides the openhandle() function for this. Unlike fileno(), it handles perl filehandles which aren't associated with OS filehandles. Unlike tell(), it doesn't produce warnings when used on an unopened filehandle From the module's documentation:

openhandle FH

Returns FH if FH may be used as a filehandle and is open, or FH is a tied handle. Otherwise "undef" is returned.

   $fh = openhandle(*STDIN);           # \*STDIN
   $fh = openhandle(\*STDIN);          # \*STDIN
   $fh = openhandle(*NOTOPEN);         # undef
   $fh = openhandle("scalar");         # undef

Solution 3

Why would you want to do that? The only reason I can think of is when you're using old style package filehandles (which you seem to be doing) and want to prevent accidentally saving one handle over another.

That issue can be resolved by using new style indirect filehandles.

open my $fh, '<', $filename or die "Couldn't open $filename: $!";

Solution 4

Perl provides the fileno function for exactly this purpose.

EDIT I stand corrected on the purpose of fileno(). I do prefer the shorter test

fileno FILEHANDLE

over

tell FH != -1

Solution 5

Tell produces a warning (so does stat, -s, -e, etc..) with use warnings (-w)

perl -wle '
    open my $fh, "<", "notexists.txt"; 
    print "can stat fh" if tell $fh
'
tell() on closed filehandle $fh at -e line 1.
-1

The alternatives fileno($fh) and eof($fh) do not produce warnings. I found the best alternative was to save the output from open.

Share:
61
SL5net
Author by

SL5net

Updated on July 15, 2022

Comments

  • SL5net
    SL5net almost 2 years

    I have imported an article using XML file via Shopware backend.

    There was a positive message 1 and even implicitly a suplier was created in database 3 (but no matching article in Item overview 2 ).

    Unfortunately the article is not in the frontend, not in the backend 2 and is not included in the database table 5.

    1. Why was data only partially taken into account when importing articles?
    2. Why was suplier crated in mysql 3 but not visible in 'Item overview' 2.
    3. Why was there no error message?
    4. Maybe it's still an error in the XML file. Which one could that be?

    Thats the source of this XML ( import 1articel with space bordered string supplier.xml ):

    `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Root>
    <articles>
    <article>
        <prices><price>
                <group>EK</group>
                <price>2.99</price>
                <pseudoprice></pseudoprice>
                <baseprice></baseprice>
            </price></prices>
        <tax>19.00</tax>
        <category><categories>101</categories></category>
        <active>1</active>
        <ordernumber>ordernumber: space bordered string supplier</ordernumber>
        <name>name: space bordered string supplier</name>
        <mainnumber>9</mainnumber>
        <supplier>   space bordered string supplier   </supplier>
    </article>
    </articles>
    </Root>`
    

    Importing finished successfully. 1 of 1

    yes new timed row in database phpmyadmin

    Manufacturer administration. See line 4

    no matching article in Item overview (backend)

    no matching article in phpmyadmin

    • kjhughes
      kjhughes over 5 years
      Is there an XSD or other XML schema you could use to validate your message? I don't work with ShopWare but <category><categories>101</categories></category> looks inside out. I'd think <categories><category>101</category></categories> would make more sense.
    • SL5net
      SL5net over 5 years
      @kjhughes There is a example XML: community.shopware.com/files/DataImportExport/… I use this (last days) preconfigured Virtualbox: github.com/sl5net/lubuntu-shopware-stack
  • Admin
    Admin about 15 years
    Oh great, good to know. Thanks.
  • chaos
    chaos about 15 years
    Well... not really. It provides fileno for the purpose of getting the system file descriptor number. Determining whether the filehandle is open is a side effect (just as it's a side effect of tell).
  • hobbs
    hobbs over 14 years
    And not a completely reliable side-effect either. It's possible to have a filehandle that's open to something other than a filedescriptor, in which case fileno sensibly returns undef. Examples are tied handles and handles opened to scalars.
  • Nick Dixon
    Nick Dixon about 13 years
    tell(FH) produces a warning with a closed filehandle. Using fileno() does not.
  • daxim
    daxim almost 13 years
  • ekerner
    ekerner over 12 years
    causes error: ... tell() on unopened filehandle ...
  • ekerner
    ekerner over 12 years
    This is the only real solution, thanks.
  • Alex Dupuy
    Alex Dupuy over 12 years
    tchrist's answer to the question @daxim links is rather spectacular, but seems to only be different from openhandle in that it will tell you that the string "STDIN" is open (which it technically is, it seems, as you can use it for print etc.) Now whether you would actually ever want to encourage this sort of thing is another question; I would tend to see the openhandle rejection of "STDIN" as more of a feature than a bug.
  • jon
    jon about 12 years
    Example reason why: Say you opened a filehandle with open(FH, "-|"). You want to make sure the forked process succeeds, which requires explicitly close FH to set $! or $? appropriately. If it didn't succeed, you want to raise an error; however, you don't want to raise an error if something else closed FH already.
  • jon
    jon about 12 years
    eof has side effects. See its docs.
  • Bill Weiss
    Bill Weiss over 11 years
    I came here from a Google search, and wanted to point out that the linked to $handle->opened(); WFM.
  • vladr
    vladr over 11 years
    @ekerner technically not an error but a warning.
  • kovacsbv
    kovacsbv over 7 years
    Scalar::Util (not the top-rated answer but should be) is the best way to do it for reasons stated in that answer.
  • U. Windl
    U. Windl over 4 years
    Another use case: You successfully opened a file handle on an NFSv4 mounted filesystem, and the NFS server reboots. Sometimes the file handle becomes invalid (EBADF). How to detect that?
  • lordadmira
    lordadmira over 3 years
    See also perldoc.pl/IO::Handle. $fh->opened.