4

如何.pl使用 Perl 扫描整个目录的内容,包括其子目录的内容,并在其中找到最新的文件?

我想构建.pl目录树中所有文件的完整文件路径的排序数组/列表。

因此,例如,如果我的基本目录是/home/users/cheeseconqueso/我想在该目录和该路径中的任何子目录中搜索.pl文件,然后.pl按日期对文件进行排序。

最终结果将是一个数组,@pl_paths,其中$pl_paths[0]将类似于/home/users/cheeseconqueso/maybe_not_newest_directory/surely_newest_file.pl

从这个结果来看,我想执行该文件,但我认为一旦我弄清楚了排序的数组,在 中执行该文件$pl_paths[0]就不会成为问题。

关于 SO有一个类似的问题,我一直在尝试修改以满足我的需要,但出于明显的原因,我现在在这里。

我用来在一个目录中获取最新文件 NAME 的代码是:

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);
print $sorted_files[0]."\n";
4

3 回答 3

13

如果你想要一个核心模块,你可以使用File::Find,但我更喜欢使用File::Find::Rule

首先,我们可以.pl在一个目录下找到所有文件

use File::Find::Rule;
my @files = File::Find::Rule->file
                            ->name('*.pl')
                            ->in($directory);

然后让我们使用map将文件名与其修改时间相关联:

my @files_with_mtimes = map +{ name => $_, mtime => (stat $_)[9] }, @files;

并按 mtime 对它们进行排序:

my @sorted_files = reverse sort { $a->{mtime} <=> $b->{mtime} } 
                @files_with_mtimes;

从那里,最新的名称在$sorted_files[0]{name}.

如果你只想找到最上面的,其实没必要做一个完整的排序,但是我能想到的最好的解决方案涉及一些稍微高级的 FP,所以如果你觉得它看起来很奇怪,完全不用担心:

use List::Util 'reduce';
my ($top_file) = reduce { $a->{mtime} >= $b->{mtime} ? $a : $b } 
  @files_with_mtimes;
于 2011-09-28T15:04:46.553 回答
5

使用File::Find::RuleSchwartzian transform,您可以在从 dir_path 开始的子树中获取具有 .pl 扩展名的最新文件。

#!/usr/bin/env perl

use v5.12;
use strict;
use File::Find::Rule;

my @files = File::Find::Rule->file()->name( '*.pl' )->in( 'dir_path' );

# Note that (stat $_ )[ 9 ] yields last modified timestamp
@files = 
   map { $_->[ 0 ] }
   sort { $b->[ 1 ] <=> $a->[ 1 ] }
   map { [ $_, ( stat $_ )[ 9 ] ] } @files;

# Here is the newest file in path dir_path
say $files[ 0 ];

map-sort-map 链是一个典型的习惯用法:获取时间戳很慢,所以我们每个文件只做一次,将每个时间戳与其文件保存在一个数组引用中。然后我们使用时间戳对新列表进行排序(比较每个 arrayref 的第二个元素),最后我们丢弃时间戳,只保留文件名。

于 2011-09-28T15:30:58.020 回答
2

使用File::Find核心模块。

于 2011-09-28T15:05:19.947 回答