如何扫描整个目录的内容,包括其子目录的内容,并使用Perl查找其中的最新.pl
文件?
我想在目录树中构建所有.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]
中执行该文件就不会有问题了。
有一个similar问题,我一直在努力修改以满足我的需求,但我现在在这里显而易见。
我用来在一个目录中获取最新文件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";
答案 0 :(得分: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;
答案 1 :(得分:4)
使用File::Find::Rule和Schwartzian 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中。然后我们使用时间戳(比较每个arrayref的第二个元素)对新列表进行排序,最后我们丢弃时间戳,只保留文件名。
答案 2 :(得分:2)
使用File::Find核心模块。