Подтвердить что ты не робот

Как найти новый созданный файл в каталоге?

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

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

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

4b9b3361

Ответ 1

Ваш путь - это "правильный" способ, если вам нужен отсортированный список (а не только первый, см. ответ Брайана). Если вам не нравится писать этот код самостоятельно, используйте 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);

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


EDIT: здесь более простая для чтения (но более длинная) версия сканирования каталога, которая также гарантирует, что в список добавляются только простые файлы:

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);

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

Ответ 2

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

@list = `ls -t`;
$newest = $list[0];

Ответ 3

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

{
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";
}

Ответ 4

Предполагая, что вы знаете $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).

Ответ 5

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

Ответ 6

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

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

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

chomp $newest_file;

print "$ newest_file\n";