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

I have a problem that continually causes me difficulties.
Some of the files that I write to with Perl can be opened by other applications.
I really want a way of finding out if the file is already open as I can then take
appropriate actions.
Some applications that I use can do this. For example, Excel will indicate a spreadsheet
is already open and an editor will not let me use a file that is open by Perl.
I keep on looking at the stat function thinking that this should give me the required information
but I cannot see how!
Can anyone give me some clues about how to overcome the curse of the open file?

Replies are listed 'Best First'.
Re: Finding if a file is open
by pc88mxer (Vicar) on May 15, 2008 at 15:07 UTC
    It appears you are trying to do this under Windows. If so, have a look at the module Win32::SharedFileOpen which appears to do what you want.
Re: Finding if a file is open
by moritz (Cardinal) on May 15, 2008 at 13:05 UTC
    flock could help you, although some editors use different tricks: they create a copy of the file with a specially mangled file name (for example vim uses sprintf ".%s.swp", $file) and check for its existence before opening a file.
      Thank you for that suggestion.
      However, I am not sure if flock will help since I want to find
      out if the file is open by another applciation before I
      try an write to it by a Perl application.

        If the other application (OA) is using file locking then flock() is the correct way. You first open() the filehandle. (There is no harm in this even if the OA is using the file.) Then you call flock() to attempt to acquire the write permission to the file. The return status tells you whether the file has been locked ('in use') by an OA.

        If the other application is using some proprietary locking scheme then of course you have to deduce what that scheme is.


        s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}

        flock will help. Just do:

        use Fcntl; # get LOCK_EX constant open F, $file or error("Can't open $file $!\n"); flock(F, LOCK_EX) or error ("Can't get exclusive lock, file open and l +ocked by other app $!\n"); close F;

        Alternatively there is a program called oh.exe in the windows resource kit that returns a list of open file handles and the programs that have them open. handle.exe which came from sysinternals (now M$) can do the job on a specific file. If you look hard enough you may be able to find the underlying code and convert this perl.

Re: Finding if a file is open
by ikegami (Patriarch) on May 15, 2008 at 15:17 UTC
    In Windows, files are locked exclusively by default. If Excel does this, you could find out by simply trying to open the file. It'll fail if it's already open.
      If Excel does this, you could find out by simply trying to open the file. It'll fail if it's already open.
      Actually, this is not true. Under cygwin perl I was able to open (using open) for writing a file that was currently opened by Excel. Trying to open that same file using WordPad, however, resulted in the familiar "The document ... is in use by another application ..." message.
        I said "If Excel does this". All you've shown is that Excel could be using some form of advisory locking instead that WordPad obeys.