如何在目录中找到最新创建的文件?

发布于 2024-07-09 10:11:30 字数 138 浏览 6 评论 0原文

Perl 中是否有一种优雅的方法来查找目录中的最新文件(按修改日期最新)?

到目前为止,我所做的是搜索我需要的文件,并为每个文件获取其修改时间,将其推入包含文件名、修改时间的数组中,然后对其进行排序。

一定会有更好的办法。

Is there an elegant way in Perl to find the newest file in a directory (newest by modification date)?

What I have so far is searching for the files I need, and for each one get it's modification time, push into an array containing the filename, modification time, then sort it.

There must be a better way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

仙女 2024-07-16 10:11:30

如果您需要一个排序列表(而不仅仅是第一个,请参阅布莱恩的答案),您的方法是“正确”的方法。 如果您不喜欢自己编写该代码,请使用

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

注意:对结果进行 define() 测试readdir() 的原因是,如果您仅测试 if (my $file = readdir($DH)),名为“0”的文件会导致循环失败

Your way is the "right" way if you need a sorted list (and not just the first, see Brian's answer for that). If you don't fancy writing that code yourself, use this

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

Personally I wouldn't go with the ls -t method - that involves forking another program and it's not portable. Hardly what I'd call "elegant"!


Regarding rjray's solution hand coded solution, I'd change it slightly:

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;

After this, @sorted_files contains the sorted list, where the 0th element is the newest file, and each element itself contains a reference to the results of stat, with the filename itself in the last element:

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

The advantage of this is that it's easier to change the sorting method later, if desired.


EDIT: here's an easier-to-read (but longer) version of the directory scan, which also ensures that only plain files are added to the listing:

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: the test for defined() on the result of readdir() is because a file called '0' would cause the loop to fail if you only test for if (my $file = readdir($DH))

狂之美人 2024-07-16 10:11:30

您不需要将所有修改时间和文件名保留在列表中,而且您可能也不应该这样做。 您需要做的就是查看一个文件,看看它是否比您之前看到的最旧的文件更旧:

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

You don't need to keep all of the modification times and filenames in a list, and you probably shouldn't. All you need to do is look at one file and see if it's older than the oldest you've previously seen:

{
    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";
}
猛虎独行 2024-07-16 10:11:30

您可以尝试使用 shell 的 ls 命令:

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

you could try using the shell's ls command:

@list = `ls -t`;
$newest = $list[0];
永不分离 2024-07-16 10:11:30

假设您知道要查看的 $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).

包装 readdirgrep 会过滤掉“.”。 和 UNIX(-ish) 文件系统中的“..”特殊文件。

Assuming you know the $DIR you want to look in:

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

The grep that wraps the readdir filters out the "." and ".." special files in a UNIX(-ish) filesystem.

倒数 2024-07-16 10:11:30

如果您不能像 @Nathan 建议的那样让 ls 为您进行排序,那么您可以通过仅保留迄今为止看到的最新修改时间和关联文件名并在每次找到时替换它来优化您的过程目录中的较新文件。 无需保留任何您知道比您迄今为止看到的最新文件更旧的文件,当然也无需对它们进行排序,因为您可以在从目录中读取时检测到哪个是最新的。

If you can't let ls do the sorting for you as @Nathan suggests, then you can optimize your process by only keeping the newest modification time and associated filename seen thus far and replace it every time you find a newer file in the directory. No need to keep any files around that you know are older than the newest one you've seen so far and certainly no need to sort them since you can detect which is the newest one while reading from the directory.

娇纵 2024-07-16 10:11:30

主题很旧,但也许有人会尝试它 - 它不可移植(仅限类 Unix 系统),但它非常简单并且有效:

chdir $directory 或 die“无法更改目录”;

我的 $newest_file = bash -c 'ls -t | 头-1';

chomp $newest_file;

打印“$newest_file \n”;

Subject is old, but maybe someone will try it - it isn't portable (Unix-like systems only), but it's quite simple and works:

chdir $directory or die "cannot change directory";

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

chomp $newest_file;

print "$newest_file \n";

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文