Как я могу найти самый новый созданный файл в каталоге? - PullRequest
20 голосов
/ 30 ноября 2008

Есть ли в Perl элегантный способ найти самый новый файл в каталоге (самый новый по дате изменения)?

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

Должен быть лучший способ.

Ответы [ 6 ]

24 голосов
/ 30 ноября 2008

Ваш путь - «правильный», если вам нужен отсортированный список (и не только первый, см. Ответ Брайана за это). Если вы не хотите писать этот код самостоятельно, используйте this

use File::DirList;
my @list = File::DirList::list('.', 'M');

Лично я бы не стал использовать метод ls -t - он включает в себя разветвление другой программы, и она не переносима. Вряд ли то, что я бы назвал "элегантным"!


Что касается решения, написанного от Rjray, я бы немного его изменил:

opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
my @files = map { [ stat "$DIR/$_", $_ ] } grep(! /^\.\.?$/, readdir($DH));
closedir($DH);

sub rev_by_date { $b->[9] <=> $a->[9] }
my @sorted_files = sort rev_by_date @files;

После этого @sorted_files содержит отсортированный список, где 0-й элемент является самым новым файлом, а каждый элемент сам содержит ссылку на результаты stat с именем самого файла в последнем элементе:

my @newest = @{$sorted_files[0]};
my $name = pop(@newest);

Преимущество этого в том, что при желании легче изменить метод сортировки.


РЕДАКТИРОВАТЬ: вот более легкая для чтения (но более длинная) версия сканирования каталогов, которая также обеспечивает добавление в список только простых файлов:

my @files;
opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
while (defined (my $file = readdir($DH))) {
  my $path = $DIR . '/' . $file;
  next unless (-f $path);           # ignore non-files - automatically does . and ..
  push(@files, [ stat(_), $path ]); # re-uses the stat results from '-f'
}
closedir($DH);

Примечание: проверка defined() на результат readdir() вызван тем, что файл с именем '0' приведет к сбою цикла, если вы будете проверять только if (my $file = readdir($DH))

14 голосов
/ 30 ноября 2008

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

{
    opendir my $dh, $dir or die "Could not open $dir: $!";

    my( $newest_name, $newest_time ) = ( undef, 2**31 -1 );

    while( defined( my $file = readdir( $dh ) ) ) {
        my $path = File::Spec->catfile( $dir, $file );
        next if -d $path; # skip directories, or anything else you like
        ( $newest_name, $newest_time ) = ( $file, -M _ ) if( -M $path < $newest_time );
    }

    print "Newest file is $newest_name\n";
}
11 голосов
/ 30 ноября 2008

вы можете попробовать использовать команду ls оболочки:

@list = `ls -t`;
$newest = $list[0];
6 голосов
/ 30 ноября 2008

Предполагая, что вы знаете $DIR, в который хотите заглянуть:

opendir(my $DH, $DIR) or die "Error opening $DIR: $!";
my %files = map { $_ => (stat("$DIR/$_"))[9] } grep(! /^\.\.?$/, readdir($DH));
closedir($DH);
my @sorted_files = sort { $files{$b} <=> $files{$a} } (keys %files);
# $sorted_files[0] is the most-recently modified. If it isn't the actual
# file-of-interest, you can iterate through @sorted_files until you find
# the interesting file(s).

grep, заключающий в себе readdir, отфильтровывает "." и ".." специальные файлы в файловой системе UNIX (-ish).

2 голосов
/ 30 ноября 2008

Если вы не можете позволить ls выполнить сортировку за вас, как подсказывает @Nathan, вы можете оптимизировать свой процесс, сохранив только самое новое время модификации и связанное с ним имя файла, и заменять его каждый раз, когда вы находите новое файл в каталоге. Вам не нужно хранить какие-либо файлы, которые, как вы знаете, старше, чем самый новый, который вы видели до сих пор, и, конечно, нет необходимости сортировать их, поскольку вы можете определить, какой из них самый новый, при чтении из каталога.

0 голосов
/ 11 апреля 2012

Тема старая, но, может быть, кто-то попробует ее - она ​​не переносима (только для Unix-подобных систем), но довольно проста и работает:

chdir $ directory или die "не может изменить каталог";

my $ newest_file = bash -c 'ls -t | head -1';

chomp $ newest_file;

печать "$ newest_file \ n";

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