6

Given the name of a file, how can I determine if the file is currently opened or in-use? (I am talking about files rather than Perl file handles.)

Please note that I am looking for a general-purpose Perl solution rather than an operating system-specific one. At a minimum, I would like something that works both on Windows and GNU/Linux-based systems.

Sam
  • 40,644
  • 36
  • 176
  • 219
  • Duplicate of http://stackoverflow.com/questions/520196/how-can-i-check-if-a-filehandle-is-open-in-perl – cppcoder Jun 01 '12 at 11:32
  • @cppcoder: The question you are referring to seems to be about file handles being open. I'm talking about files in this question. – Sam Jun 04 '12 at 06:42
  • 2
    POSIX does not provide any way to do this. Therefore, no portable solution is possible given the current portable O/S interface available. You’d have to craft some higher level approach that provides a single point of access for the opening bits. It’s like with lock files. – tchrist Jun 04 '12 at 11:19
  • @tchrist, I think I'll accept your answer if you convert that comment into an answer. – Sam Jun 18 '12 at 08:11
  • What's the solution on Windows? I don't mind if it's Windows-specific? – Helen Craigman Oct 26 '12 at 01:58
  • @HelenCraigman, I don't know; I was looking for something cross-platform. At a guess, you might be able to [use the Windows API](http://search.cpan.org/dist/Win32-API/). See [this Stack Overflow post](http://stackoverflow.com/a/12821767/238753) for a possible means to do this. I think it's better if you post this as a new Stack Overflow question about this since this question is not seeking a Windows-specific solution. – Sam Oct 26 '12 at 07:09

8 Answers8

5

POSIX does not provide any way to do this. Therefore, no portable solution is possible given the current portable O/S interface available.

You’d have to craft some higher level approach that provides a single point of access for the opening bits. It’s like with lock files.

tchrist
  • 78,834
  • 30
  • 123
  • 180
0

See the following snippet (only Linux/Unix, you don't tell us which OS you run):

In a one-liner :

perl -e 'my $file = $ARGV[0]; print "file $file is opened" if `lsof $file`;' FILE

In a script :

#!/usr/bin/env perl -w

use strict;

my $file = $ARGV[0];
print "file $file is opened\n" if `lsof $file`;

To run it :

./script.pl FILENAME
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • That's probably a good way to do it on a Unix-based system. However, I'm using Windows. A general-purpose solution that doesn't depend on the operating system would be good. – Sam May 30 '12 at 11:22
  • There's a perl module : http://search.cpan.org/~marcb/Unix-Lsof-0.0.9/lib/Unix/Lsof.pm but works only on Unix & Unix likes. Maybe working with `cygwin` can helps there. – Gilles Quénot May 30 '12 at 11:24
  • 1
    @flesk: Can you provide any more information about that module? Is it also Linux specific? If not, can you provide an example of using it to solve this problem? – Sam Jun 04 '12 at 07:29
  • 1
    On OpenBSD, it’s `fstat`, not `lsof`. – tchrist Jun 04 '12 at 11:20
-1

Try Scalar::Util

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
Sly
  • 415
  • 2
  • 8
  • I had a look at that function, but it doesn't seem to address the question. However, it's possible that I simply don't know how to use the function to do what I'm asking. – Sam May 31 '12 at 10:56
  • Yes, sorry, wrong answer. I suppose you'll have to look for windows-specific file opening functions from win32 api. – Sly May 31 '12 at 17:16
-1

Try this

use strict;
open(IN, ">test");
print IN "Hello";
close(IN);
if(fileno(IN) == undef )
{
    print "File is CLOSED\n";
}
cppcoder
  • 22,227
  • 6
  • 56
  • 81
-1

I know it has been a while but for Windows I have had some pretty good luck detecting a file is being written to by trying to lock the file (nothing fancy - just open for read, use Perl internal flock and close the file). this seems to work even on network files. I am not so sure if this works for Linux (it might on a write) and I do not know if it can detect other file readers.

-1

I read tons of post but didn't find the solution I was looking for. In my case I have a for loop creating and closing tons of files. I wanted to check if my file handler that I created was open or not. This is how you do it

use IO::Handle;

if (something matches create a file)
{
  open( $signoff_report_html, '>', "$val21");
}
elsif ( ... )
{
  #keep doing amazing stuff
}
else
{
   if ($signoff_report_html->opened()) 
   {    
      #file is ok
      print "File is opened and ready\n";       
  }
  else 
  {
      print "File was closed ... ";
  }
}
Sam B
  • 27,273
  • 15
  • 84
  • 121
-1

Try to rename the file, will fail if it is open.

Matt
  • 919
  • 6
  • 2
-2

I realize you don't want to open the file handle, but it is probably the simplest method IMO:

open my $myfh, '<', $my_file or die "Couldn't open $my_file: $!";
Bee
  • 958
  • 5
  • 12
  • I think you can typically open files in read mode even if they're already open elsewhere. – Sam Jun 04 '12 at 06:39