2011-01-12 3 views
1

В настоящее время я делаю это:Как получить список всех html-файлов во всех подкаталогах, отсортированных по алфавиту в perl?

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

     ...my processing code 

    }, $inputdir 
); 

Но я хочу, чтобы обработать все файлы в алфавитном порядке, в конечном счете, я хотел бы хранить все имена файлов в массив, отсортировать массив, а затем использовать для каждого цикла и поместил мой код обработки там, но я полностью застрял, как это сделать.

Я сделал много googling, но, как и все остальное в 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, так как он не знает, что такое заказ, пока он не прошел все файлы, поэтому мне нужно сделать сортировку потом.

ответ

2

вы можете использовать File::Basename - Разобрать пути файлов в папку, имя файла и суффикса и Schwartzian transform для сортировки файлов на основе имени файла, как,

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

fileparse() рутина File :: Basename делит путь к файлу в его $directories, $filename and (optionally) the filename $suffix., так что получите filename и передайте его в Schwartzian transform для сортировки.

0

Одним из решений могут быть метод кэширования хэша как сначала получить имени файла из File::Basename и места результатов в кэш, а затем мы можем затем просто сортировать по кэшированным значениям, то есть.,

my %cache; 
foreach my $file (@files){ 
    $cache{$file} = fileparse($file, "\.html?"); 
} 
@files = sort{$cache{$a} cmp $cache{$b}}@files; 
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, $/; 
} 
Смежные вопросы