我在目录中有以下文件,其中分隔符是"_",第三个字段是创建文件的日期。现在,我需要始终根据第一列代码选择日期最早的文件。
例:
1020300000_XXXXXXXXX_20160707193000.TXT
1020300000_XXXXXXXXX_20160707170000.TXT
1020400000_XXXXXXXXX_20160707180000.TXT
1020400000_XXXXXXXXX_20160707190000.TXT
在这种情况下,我需要因此拥有较旧的文件。
1020300000_XXXXXXXXX_20160707170000.TXT
1020400000_XXXXXXXXX_20160707180000.TXT
有人可以帮我只返回旧文件吗?
你可以这样做:
use strict;
use warnings;
use feature qw(say);
my $path = "./yourdir";
opendir (my $dh, $path) || die "Can't opendir $path: $!";
my @filelist = grep { -f "$path/$_" } readdir $dh;
my @result = sort values { # (4)
map +( $_->[1], $_->[0] ), # (3)
sort { $b->[2] cmp $a->[2] } # (2)
map [ $_, (split '_')[0,2] ], # (1)
@filelist
};
say join "n", @result;
(1) 返回对匿名三元素数组的引用列表:
([文件名,第一部分,第三部分],[文件名,第一部分,第三部分],...)
(2) 使用创建日期(第三部分)按降序(从最新到最旧)返回排序列表。
(3) 从输入列表中引用的每个数组中返回一个由"第一部分"和"文件名"组成的列表:
(第一部分, 文件名, 第一部分, 文件名, ...
(4) 使用列表创建一个匿名哈希(这里的大括号不分隔块或表达式,而是定义哈希)。所有第一部分都成为键,所有文件名都成为值。由于文件名以前是从最新到最旧的排序的,因此每个键都与最旧的文件名相关联,该文件名覆盖了同一键的最终最近的先前值。
您可以利用日期在 YYYYMMDDHHMISS 中的事实,只需对它们进行排序并使用哈希仅获取最高值,返回所需的条目:
sub get_oldest_two {
my (@files) = @_;
my @sorted = sort { [split(/_/, $a)]->[2] lt [split(/_/, $b)]->[2] } @files;
my %file_dates = map { [split(/_/, $_)]->[0] => $_ } @sorted;
return reverse(sort((values(%file_dates))[0..1]));
}
我认为你的输出应该是
1020300000_XXXXXXXXX_20160707170000.TXT
1020400000_XXXXXXXXX_20160707180000.TXT
.如果没有,我不知道你的要求是什么。无论如何,我希望这是你需要的
#!/usr/bin/perl
use Data::Dumper;
# folder saves the files
$folder = "test";
# save file names as array
@files = `ls $folder`;
chomp @files;
foreach $file (@files){
#split filename to 3 columns e.g.
#1020300000 XXXXXXXXX 20160707170000.TXT
($col_1, $col_2, $col_3) = split(/_/, $file);
#delete .TXT
$col_3 =~ s/.txt$//i;
#use my to create new @tmp every loop
my @tmp = ($col_3, $file);
#%outpput is our target result
#col_1 is key, the hash should look like this
# '1020300000' => [
# '20160707170000', <= this is col_3, will be used to compare later
# '1020300000_XXXXXXXXX_20160707170000.TXT' <= condidate of the result
# ]
unless(defined $output{$col_1}){
$output{$col_1} = @tmp;
next;
};
$saved_col_3 = $output{$col_1}->[0];
#because $col_1 are the same (key), so compare their col_3 value
if($col_3 < $saved_col_3){
#update if this one is smaller
$output{$col_1} = @tmp;
}
}
#print Dumper(%output);
#so....
foreach (keys %output){
print "$output{$_}->[1]n";
}