【问题标题】:How do you check if a file is open using Perl?如何使用 Perl 检查文件是否打开?
【发布时间】:2012-06-04 14:42:49
【问题描述】:

给定文件的名称,我如何确定文件当前是打开还是正在使用? (我说的是文件而不是 Perl 文件句柄。)

请注意,我正在寻找通用的 Perl 解决方案,而不是特定于操作系统的解决方案。至少,我想要在 Windows 和基于 GNU/Linux 的系统上都工作的东西。

【问题讨论】:

  • @cppcoder:您所指的问题似乎与文件句柄打开有关。我说的是这个问题中的文件。
  • POSIX 没有提供任何方法来做到这一点。因此,鉴于当前可用的便携式 O/S 接口,没有便携式解决方案是可能的。您必须设计一些更高级别的方法,为开始位提供单点访问。就像锁定文件一样。
  • @tchrist,如果您将该评论转换为答案,我想我会接受您的回答。
  • Windows 上的解决方案是什么?我不介意它是否是特定于 Windows 的?

标签: perl file


【解决方案1】:

POSIX 没有提供任何方法来做到这一点。因此,鉴于当前可用的便携式 O/S 接口,没有便携式解决方案是可能的。

您必须设计一些更高级别的方法,为开始位提供单点访问。就像锁定文件一样。

【讨论】:

    【解决方案2】:

    看下面的sn-p(只有Linux/Unix,你不用告诉我们你运行的是哪个操作系统):

    单行:

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

    在脚本中:

    #!/usr/bin/env perl -w
    
    use strict;
    
    my $file = $ARGV[0];
    print "file $file is opened\n" if `lsof $file`;
    

    运行它:

    ./script.pl FILENAME
    

    【讨论】:

    • 这可能是在基于 Unix 的系统上执行此操作的好方法。但是,我使用的是 Windows。一个不依赖于操作系统的通用解决方案会很好。
    • 有一个 perl 模块:search.cpan.org/~marcb/Unix-Lsof-0.0.9/lib/Unix/Lsof.pm 但仅适用于 Unix 和 Unix 之类的。也许与cygwin 合作可以帮助那里。
    • @flesk:您能否提供有关该模块的更多信息?它也是Linux特定的吗?如果没有,你能提供一个使用它来解决这个问题的例子吗?
    • 在 OpenBSD 上,它是 fstat,而不是 lsof
    【解决方案3】:

    试试这个

    use strict;
    open(IN, ">test");
    print IN "Hello";
    close(IN);
    if(fileno(IN) == undef )
    {
        print "File is CLOSED\n";
    }
    

    【讨论】:

    • 我问的是文件而不是文件句柄。
    【解决方案4】:

    我知道这已经有一段时间了,但是对于 Windows,我很幸运地通过尝试锁定文件来检测正在写入的文件(没什么特别的 - 只是打开读取,使用 Perl 内部群并关闭文件)。这似乎甚至适用于网络文件。我不太确定这是否适用于 Linux(它可能在写入时),我不知道它是否可以检测到其他文件读取器。

    【讨论】:

      【解决方案5】:

      试试Scalar::Util

      Scalar::Util 模块为此提供了openhandle() 函数。与fileno() 不同,它处理与操作系统文件句柄无关的perl 文件句柄。与tell() 不同,它在用于未打开的文件句柄时不会产生警告来自模块的documentation

      打开句柄 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
      

      【讨论】:

      • 我看过那个函数,但它似乎没有解决这个问题。但是,我可能根本不知道如何使用该功能来完成我的要求。
      • 是的,对不起,错误的答案。我想您必须从 win32 api 中寻找特定于 windows 的文件打开功能。
      【解决方案6】:

      我阅读了大量帖子,但没有找到我正在寻找的解决方案。就我而言,我有一个 for 循环创建和关闭大量文件。我想检查我创建的文件处理程序是否打开。你就是这样做的

      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 ... ";
        }
      }
      

      【讨论】:

        【解决方案7】:

        尝试重命名文件,如果打开会失败。

        【讨论】:

          【解决方案8】:

          我知道你不想打开文件句柄,但这可能是 IMO 最简单的方法:

          open my $myfh, '<', $my_file or die "Couldn't open $my_file: $!";
          

          【讨论】:

          • 我认为您通常可以以读取模式打开文件,即使它们已经在其他地方打开。
          猜你喜欢
          • 1970-01-01
          • 2015-11-28
          • 2011-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-20
          • 2012-08-30
          相关资源
          最近更新 更多