Получение списка файлов, отсортированных по дате модификации в Perl
Я пытаюсь получить список файлов, отсортированных по дате изменения. Я изменил пример программы из сортировка файлов каталогов и списков по дате и времени и попытался запустить его.
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 "$keyst", scalar localtime($files{$keys}), "n";
}
Я запускаю это на моей 32-разрядной машине Windows XP, используя Strawberry Perl версии 5.12.1.0.
Список каталогов в Windows выглядит следующим образом:
Вывод:
Вывод не имеет для меня особого смысла. Что такое что-то не так с этим фрагментом кода, и как именно цикл foreach
сортирует список файлов?
4 ответа:
В
get_sorted_files
,$dir
это глобус, а не имя каталога. Возможно, вы имели в виду$path
?my %hash = map {$_ => (stat($_))[9]} map { "$path/$_" } # $path, not $dir grep { m/.*/i } readdir $dir;
С этим кодом по меньшей мере 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
является дескриптором каталога; именно там находится глобус (0x...) исходит от него. Во-вторых, все даты модификации читаются "Wed Dec 31 16: 00: 00 1969", потому что вы передавали неправильное имя пути кstat
.(stat($_))[9]
возвращал пустой список (потому что вы искали файл типаGLOB(0x3f9b38)status.txt
вместо этого правильного пути) и поэтому хэш фактически оказался содержащим имена файлов как ключи, так и значения. Первое имя файла было ключом, второе-его значением, третье-следующим ключом и так далее.localtime
преобразовывал имя файла в число (получая 0), а затем преобразовывал время эпохи 0 (1-Jan-1970 0:00:00 UTC) в ваш часовой пояс. В-третьих, он ожидает, что$path
закончится разделителем каталогов, а вы передавали"."
. Вам нужно будет пройти"./"
, или еще лучше, исправить это так, чтобы функция добавляет разделитель, если это необходимо. В-четвертых,grep
больше ничего не делал и должен быть удален. (В исходном коде он выбирал только определенные имена файлов, но вы изменили шаблон, чтобы соответствовать чему-либо.)Что касается того, как он сортирует имена файлов:
get_sorted_files
возвращает список имен путей и времени модификации, которые вы сохраняете в хэше%files
.keys %files
возвращает список ключей (имена файлов) и сортирует их по числовому сравнению соответствующего значения (имя файла). время модификации).
Используйте функцию Perl S sort. Это быстрее, и вы получите то, что хотите, без гашиша.
Зная вышесказанное, мы можем сказать примерно следующее:Размер файла, затем возраст файла:
@с = сортировка {-ы $а -с $б || -м $Б -М $С} @а;
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; }
Для действительно больших каталогов вы можете обнаружить, что Perl значительно медленнее, чем использование собственных инструментов для сортировки. Например, на моей машине, в огромном каталоге (341k файлов), это занимает около 1,5 минут:
Но код в приведенном выше решении (с использованиемmy $mostrecent = `/bin/ls --full-time -lta $dir | head -1 2>/dev/null`;
opendir
иsort -M
) занимает от 30 до 45 секунд больше. Мало того, что это значительно быстрее, вы также можете избежать Perl хранения всего массива в памяти, что само по себе может быть выигрышем.Обратите внимание, что вышеизложенное относится к довольно высококлассной системе Linux blade, поэтому YMMV на компьютер / ОС...