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

the*_*ory 7 filesystems perl filenames case-insensitive

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

考虑一下HFS +(Mac OS X):

> perl -E 'say "yes" if -e "/TMP"'
yes
Run Code Online (Sandbox Code Playgroud)

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

到目前为止我尝试过的:

  • glob 使用字符类:它在Windows上不起作用:

    > perl -E "say for glob "C:\\Perl"
    C:\Perl
    > perl -E "say for glob "C:\\[Pp][Ee][Rr][Ll]"
    
    Run Code Online (Sandbox Code Playgroud)

    注意最后一个命令缺少输出.:-(

  • opendir/ readdir:工作,但读取整个目录似乎效率很低:

      > perl -E "opendir my $dh, 'C:\\'; say for grep { lc $_ eq 'perl' } readdir $dh; close $dh"
    Perl
    
    Run Code Online (Sandbox Code Playgroud)

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

the*_*ory 4

opendir//readdir解决方案grep是正确的。Neil Bowers通过 Twitter引用了perlport的这段引言:

不要指望文件名通配。使用opendirreaddir、 和closedir代替。

@miyakawa通过 Twitter表示,没有为此进行的系统调用,即使有,它也不会是可移植的。

鉴于@mob 的回答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;
}
Run Code Online (Sandbox Code Playgroud)