我想检查两个文件句柄是指同一个文件。为了做到这一点,我可以使用应用到每个文件句柄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);
不能在一般的(可移植的)来完成,†什么是可以理解的,一个“文件”句柄不必与文件的所有关联。有一两件事你可以做的是记录每个文件句柄的fileno。
因此,打开文件时
my %filename_fileno;
open my $fh, '>', $file or die "Can't open $file: $!";
$filename_fileno{fileno $fh} = $file;
然后在需要的时候,你可以去查一下‡
say "Filename is: ", $filename_fileno{fileno $fh};
不要忘了从哈希删除的条目时该文件被关闭(是)
delete $filename_fileno{fileno $fh};
close $fh;
因此,这些应该是在实用功能。考虑到更多的照顾是必要的,因为在‡脚注概述,共此将使一个可爱的小模块。然后,一个也可以考虑延长(继承)相关的模块,如Path::Tiny。
注意:您可以不写,从这样的单独文件句柄的文件。每个操作文件句柄跟踪下文件句柄的最后文件中,这样写道将由其他文件句柄揍中间写。
注意:使用词法文件句柄(my $fh
),而不是水珠(FH
),使用三个参数open
,并经常检查open
电话。
†在某些(大多数?)的Linux系统,你可以使用文件系统/proc
say readlink("/proc/$$/fd/" . fileno $fh);
和更多的(所有?)的Unix-Y系统可以使用(设备和)inode编号
say for (stat $fh)[0,1];
‡链接,这两个软(符号)和硬,可以用来改变数据和具有不同的名称。因此,我们可以有不同的文件名,但同样的“文件”(数据)。
在Windows系统上,检查的最佳方式this post给出,但对于其中一个将不得不使用其他答案的方法(解析输出),据我可以告诉硬链接的情况。
此外,不规范的名称,以及不同的资本化(对大小写不敏感的系统),在某些系统上的短/长文件名,(多?)......可以为同一个文件的不同名称。这是比较容易清理,使用模块,但需要添加。
在大多数(全部?)其他系统的inode的概念,任何可用的stat
一样的功能,使这些非问题,因为设备+ inode的唯一指的是数据。
由于ikegami对这个意见。
是,在某些系统+设备的组合,stat
可以使用。
use File::stat;
my $st1 = stat($fh1)
or die $!;
my $st2 = stat($fh2)
or die $!;
say $st1->dev == $st2->dev && $st1->ino == $st2->ino ? "same" : "different";
值得注意的是,这不会对NTFS或FAT32,其中一个你似乎是使用工作。
你应该把你的程序保持其本身的轨道,但是这谈何容易。这是相当难以确定,如果两个路径指向同一个文件时,你有硬链接,软链接,与.
/ ..
路径,资本/斜线差异,短/长名,常规/ UNC路径,股份等抗衡
例如,下面所有的路径可能是指同一个文件:
C:\Moo\Foo Bar.txt
C:\Hardlink\Foo Bar.txt
C:\Softlink\Foo Bar.txt
C:\.\Moo\Foo Bar.txt
C:\Baz\..\Moo\Foo Bar.txt
c:\moo\foo bar.txt
C:/Moo/Foo Bar.txt
C:\Moo\FOOBAR~1.TXT
\\?\C:\Moo\Foo Bar.txt
\\127.0.0.1\C$\Moo\Foo Bar.txt
Z:\Moo\Foo Bar.txt
所有但最后两个可以通过标准化处理。