如何在 Perl 中找到文件的大小写保留名称?

How do I find the case-preserved name of a file in Perl?

在不区分大小写的文件系统(例如 NTFS 或 HFS+)上,给定一个文件名,确定文件名的大小写保留版本的最有效方法是什么?

考虑 HFS+ (Mac OS X):

> perl -E 'say "yes" if -e "/TMP"'
yes

它说它当然存在,但我不知道它的外壳是如何保存的。确定实际情况的最有效方法是什么?

到目前为止我尝试过的:

认为应该有一些核心操作系统指令或其他东西来更有效地获取这些信息是不是很疯狂?

glob 函数无法识别正则表达式样式字符 类 ([Pp], [Ee])。相反,它使用 csh 风格的通配符扩展。要完成您的示例任务,您需要使用语法

glob("C:\{P,p}{E,e}{R,r}{L,l}")

我不知道 glob 的实现细节,但它似乎还需要检查目录中的每个文件,并且不一定比你的 readdir/grep 更有效成语.

或者更简洁(同样,不一定更有效),glob/grep 成语:

perl -E "say for grep {/C:\PERL/i} glob('C:\*')"

(已更新,仍未测试)

在 Windows、

>perl -MWin32 -E"say Win32::GetLongPathName($ARGV[0])" "C:\PROGRAM FILES"
C:\Program Files

>perl -MWin32 -E"say Win32::GetLongPathName($ARGV[0])" C:\PROGRA~1
C:\Program Files

在 unix 上,fcntlF_GETPATH 函数就可以了。

opendir/readdir/grep 解决方案是正确的。 Via Twitter, Neil Bowers points to this quotation from perlport:

Don't count on filename globbing. Use opendir, readdir, and closedir instead.

@miyagawa, also via Twitter,表示没有系统调用,如果有,也不能移植。

并且考虑到 @mob's answer and comments from David Golden 建议 glob 会比 opendirreaddir 更贵,无论如何,似乎没有其他办法。

下面是我编写的用于查找目录中给定基本名称的所有案例的函数:

sub _actual_filenames {
    my $dir = shift;
    my $fn = lc shift;
    opendir my $dh, $dir or return;
    return map { File::Spec->catdir($dir, $_) }
        grep { lc $_  eq $fn } readdir $dh;
}