35

Is there a way to check if a file is already open in Perl? I want to have a read file access, so don't require flock.

 open(FH, "<$fileName") or die "$!\n" if (<FILE_IS_NOT_ALREADY_OPEN>);
 #  or something like
 close(FH) if (<FILE_IS_OPEN>);
brian d foy
  • 129,424
  • 31
  • 207
  • 592

5 Answers5

38

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.

Community
  • 1
  • 1
chaos
  • 122,029
  • 33
  • 303
  • 309
24

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
Community
  • 1
  • 1
brady
  • 241
  • 2
  • 2
  • 2
    [openhandle caveats](http://stackoverflow.com/questions/3807231/how-can-i-test-if-i-can-write-to-a-filehandle/4200474#4200474) – daxim May 19 '11 at 11:03
  • 2
    This is the only real solution, thanks. – ekerner Sep 14 '11 at 07:16
  • 1
    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. – Alex Dupuy Nov 14 '11 at 21:12
  • I came here from a Google search, and wanted to point out that the linked to `$handle->opened();` WFM. – Bill Weiss Oct 07 '12 at 01:45
11

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: $!";
Leon Timmermans
  • 30,029
  • 2
  • 61
  • 110
  • matt: try Perl::Critic for better style – Alexandr Ciornii Feb 13 '09 at 21:45
  • 1
    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. – jade Feb 29 '12 at 18:46
  • 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? – U. Windl Oct 10 '19 at 09:58
10

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

chaos
  • 122,029
  • 33
  • 303
  • 309
converter42
  • 7,400
  • 2
  • 29
  • 24
  • 1
    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). – chaos Feb 08 '09 at 20:56
  • 1
    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. – hobbs Aug 29 '09 at 22:55
  • 1
    tell(FH) produces a warning with a closed filehandle. Using fileno() does not. – Nick Dixon Mar 11 '11 at 15:10
1

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.

CoffeeMonster
  • 2,160
  • 4
  • 20
  • 34