【问题标题】:Sorting directory filenames with Perl使用 Perl 对目录文件名进行排序
【发布时间】:2011-07-04 17:51:17
【问题描述】:

我想按名称对目录中的文件进行排序/打印。我的代码将它们全部列出,但排序有偏差。这是我的代码和结果。任何建议都将受到欢迎!

my $file;
opendir (DIR, "$dir");
while ($file = readdir(DIR)) {
    push (my @files, $file);
    @files = sort {$a cmp $b} @files;   #NOT sorting!
    foreach $file (@files) {
        print "$file\n";
    }
}

这里是“排序”的结果:

Screenshot-Chess_-_Human_versus_GNUchess.png  
test.html  
katyperry.gif  
test.cgi  
Californication.S04E05.HDTV.XviD-ASAP.avi  
FreeWatch_13.exe  
proxy.jpg  
test.pl-  
.  
attachment2.jpg  
attachment.jpg  
Californication.S04E06.HDTV.XviD-LOL.avi  
Californication.S04E07.HDTV.XviD-LOL.avi  
boxter.jpg  
..  

【问题讨论】:

    标签: perl sorting


    【解决方案1】:

    您正在构建一系列单元素列表,对每个列表进行排序(这是一个无操作)并打印它。您要做的是将整个文件列表读入一个列表,然后对其进行排序,如下所示:

    my $file;
    my @files;
    opendir (DIR, "$dir");
    while ($file = readdir(DIR)) {
        push (@files, $file);
    }
    @files = sort {$a cmp $b} @files;
    foreach $file (@files) {
        print "$file\n";
    }
    

    【讨论】:

    • 更好的是,将 while 循环替换为 @files = readdir(DIR)
    • @andy-lester:就此而言,print join("\n", sort { $a cmp $b } readdir(DIR))."\n";
    • 谢谢!我不敢相信我错过了如此重要的东西。感谢 StackOverflow 和所有帮助我解决问题的人!
    • 另外添加 lc 函数可以避免由于名称大写导致的奇怪结果:@files = sort {lc($a) cmp lc($b)} @files;
    【解决方案2】:

    另一种方式,使用File::Slurp

    use warnings; 
    use strict; 
    use File::Slurp;
    use Data::Dumper;
    
    my @files = read_dir($dir);
    @files = sort @files;
    print Dumper(\@files);
    

    这负责打开和关闭目录,检查是否成功, 并自动排除特殊。和 .. 目录,你可能 不想。

    【讨论】:

      【解决方案3】:

      my @fileswhile 循环的词法范围内将始终导致在循环的每次迭代中创建一个新的@files 数组。因此,在任何时候,@files 都将只包含一个元素,因此排序毫无意义。 Now see Anomie's answer.

      【讨论】:

        【解决方案4】:

        说真的,你做的工作比你必须做的要多。

        use warnings;
        use strict;
        use autodie;
        use File::Spec::Functions qw'no_upwards';
        
        my $dir = '.';
        
        opendir my($dh), $dir;
        for my $file ( no_upwards sort readdir $dh ){
          print "$file\n";
        }
        closedir $dh;
        

        【讨论】:

          【解决方案5】:

          对路径进行排序很棘手,因为在 ASCII 排序序列中,路径分隔符斜杠 (/) 位于大多数路径字符之前,但并非所有字符之前,尤其是点和破折号。

          通过斜线分割将路径分成路径元素。用 cmp 比较路径元素的字母数字。如果是平局,则元素较少的路径排在元素较多的路径之前。

          请务必切掉所有换行符。将 &bypath 子例程与 Perl 排序命令一起使用:sort bypath @files;

          sub bypath {
            my @a = split m'/', $a;
            my @b = split m'/', $b;
            for ( my $i = 0; $i<=$#a; $i++ ) {
              last if $i > $#b;
              return $a[$i] cmp $b[$i] if $a[$i] cmp $b[$i];
              }
            return $#a <=> $#b;
            }
          

          示例结果:

          • 这个
          • 这个/那个
          • 这个/那个/其他
          • 这个/那个/其他/filea
          • this/that/other/fileb
          • this/that/other.new/filea

          【讨论】:

            【解决方案6】:
            use v5.10;
            say for sort do { opendir( my $fh, $dir ); readdir($fh) };
            

            【讨论】:

              【解决方案7】:

              我不明白你们为什么要这么复杂地做这件事。这非常适合对文件或文件夹进行排序。

              opendir (my $DIR, "$dir") || die "Error while opening $dir: $!\n";
              
              foreach my $dirFileName(sort readdir $DIR)
              {
                    next if $dirFileName eq '.' or $dirFileName eq '..';
                    print("fileName: $dirFileName ... \n");
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-07-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-01-14
                • 1970-01-01
                • 1970-01-01
                • 2012-07-27
                相关资源
                最近更新 更多