1

目前我正在这样做:

# Find all files
File::Find::find(
    sub {
        my $file = $_;
        return if -d $file; 
        return if $file !~ /(.*)\.htm$/;

        ...my processing code

    }, $inputdir
);

但是我想按字母顺序处理所有文件,最终我想将所有文件名存储在一个数组中,对数组进行排序,然后使用 for each 循环并将我的处理代码放在那里,但我完全不知道如何做。

我已经做了很多谷歌搜索,但就像 perl 中的其他所有内容一样,有 100 种方法可以做所有事情,但似乎没有一个能让我做我想做的所有事情,即所有以 .html 结尾的文件,所有子目录在特定目录中,并根据文件名而不是目录结构按字母顺序排序。

谁能帮我吗?我知道这可以很容易地完成,我只是想不通。

谢谢 :)

编辑:我试过这样做:

File::Find::find(
    sub {
        #Only process html files
        my $file = $_;
        return if -d $file; 
        return if $file !~ /(.*)\.htm$/;

        push(@files, $File::Find::name);

    }, $inputdir 
);

但是,如果我对数组 @files 进行排序,它将根据整个字符串对其进行排序,我只想根据文件名对其进行排序。我不认为有办法用 File::find:find 来做,因为在遍历所有文件之前它无法知道顺序是什么,所以我需要在之后进行排序。

4

4 回答 4

2

您可以使用File::Basename - 将文件路径解析为目录、文件名和后缀,并使用Schwartzian 变换根据文件名对文件进行排序,例如,

 @files = map { $_->[0] }
    sort { $a->[1] cmp $b->[1] }
    map { [$_, fileparse($_, "\.html?")] } @files; 

File::Basename的fileparse()例程将一个文件路径分成它的$directories, $filename and (optionally) the filename $suffix.so getfilename并传递给它Schwartzian transform进行排序。

于 2011-01-12T05:54:06.883 回答
1

File::Next有排序选项。

于 2011-01-12T08:01:20.977 回答
0

另一种解决方案可能是哈希缓存方法,例如首先从File::Basename获取文件名并将结果放入缓存中,然后我们可以简单地对缓存的值进行排序,即,

my %cache;
foreach my $file (@files){
  $cache{$file} = fileparse($file, "\.html?");
}
@files = sort{$cache{$a} cmp $cache{$b}}@files;
于 2011-01-14T09:42:06.323 回答
0

不会是性能赢家,但包含在内是为了展示出色的File::Find::Rule,它可能很有趣并且对于小文件树来说是可以接受的。也使用Path::Class

use warnings;
use strict;
use File::Find::Rule;
use Path::Class qw( file );

my @files = map { file($_) }
    File::Find::Rule->file()
    ->name("*\.html")
    ->in(shift||".");

for my $file ( sort { lc($a->basename) cmp lc($b->basename) } @files )
{
    print $file, $/;
}
于 2011-01-14T20:02:32.073 回答