Получение списка файлов, отсортированных по дате модификации в Perl - PullRequest
4 голосов
/ 10 января 2011

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

sub get_sorted_files {
    my $path = shift;
    opendir my($dir), $path or die "can't opendir $path: $!";
    my %hash = map {$_ => (stat($_))[9]}
               map  { "$dir$_" }
               grep { m/.*/i }
               readdir $dir;
    closedir $dir;
    return %hash;
}

my %files = get_sorted_files(".");
foreach my $keys (sort{$files{$a} <=> $files{$b}} keys %files) {
    print "$keys\t", scalar localtime($files{$keys}), "\n";
}

Я запускаю это на своей Windows32-разрядная машина XP, использующая Strawberry Perl версия 5.12.1.0.

Список каталогов в Windows:

alt text

Вывод:

alt text

Вывод не имеет большого смысла для меня.Что не так с этим фрагментом кода и как именно цикл foreach сортирует список файлов?

Ответы [ 4 ]

7 голосов
/ 11 января 2011

Есть как минимум 2 проблемы с этим кодом.Вот лучшая версия:

use strict;
use warnings; # I bet you weren't using this, because it produced a lot

sub get_sorted_files {
   my $path = shift;
   opendir my($dir), $path or die "can't opendir $path: $!";
   my %hash = map {$_ => (stat($_))[9] || undef} # avoid empty list
           map  { "$path$_" }
           readdir $dir;
   closedir $dir;
   return %hash;
}

my %files = get_sorted_files("./");
foreach my $key (sort{$files{$a} <=> $files{$b}} keys %files) {
   print "$key\t", scalar localtime($files{$key}), "\n";
}

Сначала вы переименовали $dir в исходном коде в $path, но не изменили его в строке map.Ваш $dir является дескриптором каталога;вот откуда приходит GLOB (0x ...).

Во-вторых, все даты модификации читаются как «Ср 31 декабря 16:00:00 1969», потому что вы передавали неверный путь к stat.(stat($_))[9] возвращал пустой список (потому что вы искали файл типа GLOB(0x3f9b38)status.txt вместо правильного имени пути), и поэтому хэш фактически содержал имена файлов как ключи и значения.Первое имя файла было ключом, второе - его значением, третье - следующим ключом и так далее.localtime преобразовывал имя файла в число (получая 0), а затем преобразовывал время эпохи 0 (1 января 1970 г. 0:00:00 UTC) в ваш часовой пояс.

В-третьих, он ожидает $path заканчивается разделителем каталогов, и вы передаете ".".Вам нужно будет передать "./", или, что еще лучше, исправить это так, чтобы функция добавляла разделитель при необходимости.

В-четвертых, grep больше ничего не делал и должен быть удален.(В исходном коде он выбрал только определенные имена файлов, но вы изменили шаблон так, чтобы он совпадал с чем угодно.)

Что касается порядка сортировки имен файлов: get_sorted_files возвращает список путей и времен изменения, которыеВы сохраняете в хэш %files.keys %files возвращает список ключей (имен файлов) и сортирует их по числовому сравнению соответствующего значения (время модификации).

6 голосов
/ 22 декабря 2012

Используйте функцию Perl sort .Это быстрее, и вы получите то, что вы хотите без хэша.

Размер файла, затем возраст файла:

@ s = sort {-s $ a <=> -s $ b ||-M $ b <=> -M $ a} @a;

Зная вышесказанное, можно сказать что-то вроде следующего:

sub get_sorted_files {
   my $path = shift;
   opendir my($dirh), $path or die "can't opendir $path: $!";
   my @flist = sort {  -M $a <=> -M $b } # Sort by modification time
               map  { "$path/$_" } # We need full paths for sorting
               readdir $dirh;
   closedir $dirh;
   return @flist;
}
4 голосов
/ 10 января 2011

В get_sorted_files, $dir - это глобус, а не имя каталога. Возможно, вы имели в виду $path?

my %hash = map {$_ => (stat($_))[9]}
           map  { "$path/$_" }              # $path, not $dir
           grep { m/.*/i }
           readdir $dir;
0 голосов
/ 14 октября 2013

Для действительно больших каталогов вы можете обнаружить, что Perl значительно медленнее, чем использование собственных инструментов для сортировки.Например, на моей машине в огромном (341 тыс. Файлов) каталоге это занимает около 1,5 минут:

my $mostrecent = `/bin/ls --full-time -lta $dir | head -1 2>/dev/null`;

Но код в приведенном выше решении (с использованием opendir и sort -M) занимает30-45 секунд дольше.Мало того, что это значительно быстрее, вы также можете избежать хранения всего массива в памяти в Perl, что само по себе может быть выигрышем.

Обратите внимание, что вышеприведенное относится к блейд-системе Linux довольно высокого класса, поэтомуYMMV на компьютер / ОС ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...