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

时间:2015-02-19 17:40:07

标签: perl filesystems filenames case-insensitive

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

考虑使用HFS +(Mac OS X):

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

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

到目前为止我尝试过:

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

    > perl -E "say for glob "C:\\Perl"
    C:\Perl
    > perl -E "say for glob "C:\\[Pp][Ee][Rr][Ll]"
    

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

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

      > perl -E "opendir my $dh, 'C:\\'; say for grep { lc $_ eq 'perl' } readdir $dh; close $dh"
    Perl
    

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

3 个答案:

答案 0 :(得分:4)

在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上,fcntl的{​​{3}}功能可以。

答案 1 :(得分:4)

opendir / readdir / grep解决方案是正确的。 Via Twitter,Neil Bowers指出来自perlport的引文:

  

不要指望文件名为globbing。请改用opendirreaddirclosedir

@miyagawa,也是via Twitter,表示没有系统调用,如果有,它将不可移植。

鉴于@mob's answer和评论from David Golden表明globopendirreaddir更贵,无论如何,似乎没有其他方式。

所以这里是我编写的函数,用于查找目录中给定basename的所有案例:

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

答案 2 :(得分:2)

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:\*')"

(已更新,尚未测试)