如何确定两个句柄是否引用同一个文件

fab*_*zio 3 perl handler stat filehandler

我想检查两个文件句柄是否引用同一个文件。为此,我可以使用stat应用于每个文件句柄的功能吗?提前致谢

my $file = 'C:\temp\file.txt');
open( TXT1, "> $file" );
open( TXT2, "> $file" );
print( "The handles refer to the same file!") if (\TXT1 eq \TXT2);
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 5

通常不能(便携式地)做到这一点,完全不必考虑“文件”句柄与文件的关联,这是可以理解的。有一两件事你可以做的是记录的fileno每个文件句柄。

因此,当打开文件时

my %filename_fileno;

open my $fh, '>', $file or die "Can't open $file: $!";

$filename_fileno{fileno $fh} = $file;
Run Code Online (Sandbox Code Playgroud)

然后您可以在需要时查找它

say "Filename is: ", $filename_fileno{fileno $fh};
Run Code Online (Sandbox Code Playgroud)

当该文件被关闭时,别忘了从哈希中删除条目

delete $filename_fileno{fileno $fh};
close $fh;
Run Code Online (Sandbox Code Playgroud)

因此,这些应该在实用程序函数中。如脚注所概述,鉴于需要更多的照顾,总的来说这将构成一个不错的小模块。然后,也可以考虑扩展(继承自)一个相关的模块,例如Path :: Tiny

注意:您不能像问题中那样从单独的文件句柄写入文件。每个文件句柄上的操作都会跟踪文件句柄在文件中的最后位置,因此写入将破坏另一个文件句柄的中间写入。

注意:使用词法文件句柄(my $fh)而不是globs(FH),使用三个参数open,并始终检查opencall


  在某些(大多数?)Linux系统上,您可以使用/proc文件系统

say readlink("/proc/$$/fd/" . fileno $fh);
Run Code Online (Sandbox Code Playgroud)

在更多(全部?)上,Unix-y系统可以使用(设备和)索引节点号

say for (stat $fh)[0,1];
Run Code Online (Sandbox Code Playgroud)

  软链接(符号链接)和硬链接(硬链接)都可用于更改数据并具有不同的名称。因此,我们可以使用不同的文件名,但使用相同的“文件”(数据)。

在Windows系统上,检查的最佳方式中给出这个职位,除了对其中一个将不得不使用其他答案的方法(解析输出)的硬链接的情况下,据我可以告诉。

另外,非规范名称以及大小写不同(在不区分大小写的系统上),某些系统上的短/长名称(更多?)...可以为同一文件指定不同的名称。使用模块可以更轻松地进行清理,但也需要添加它。

在大多数(所有其他)系统上,inode的概念和任何可用stat的类似功能使这些问题不再存在,因为device + inode唯一地引用数据。

感谢池上对此发表评论。