我想从此data.list
目录中检索行数:Project/chris/company/Delta/force/run_20210619_df/total/data.list
但问题是run_20210619_df
更改,并且每次将新数据更新到 data.list 时都会被替换。
可以说原始目录是:
Project/chris/company/Delta/force/run_20210619_df/total/data.list
但今天data.list
正在更新,因此在仍然存在的情况下形成了一个新目录run_20210619_df
:Project/chris/company/Delta/force/run_20210624_df/total/data.list
并且两个目录都包含data.list
我可以制作一个始终可以读取的脚本吗最新版本 data.list
?在这种情况下它的内部run_20210624_df
我从这个开始:
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $files = './Project/chris/company/Delta/force/*/total/data.list';
my $hashref;
for my $file ( glob($files) ) {
my($date) = (split('/',$_))[6];
if( $hashref->{$id) and $date gt $hashref->{$id}{date} ) {
$hashref->{$id}{file} = $file;
$hashref->{$id}{date} = $date;
$hashref->{$id}{count} = count_lines($file);
} else {
$hashref->{$id}{file} = $file;
$hashref->{$id}{date} = $date;
$hashref->{$id}{count} = count_lines($file);
}
}
say Dumper($hashref);
sub count_lines {
my $fname = shift;
my $count;
open my $fh, '<', $fname or die $!;
$count++ while <$fh>;
close $fh;
return $count;
}
不幸的是,当我运行脚本时,它无法检测到要从中提取信息的 data.list 。因此打印 3 次,因为我有 3 个不同的 $date 文件
答案1
使用该函数按每个文件的修改时间戳对 glob 进行排序stat
。
例如
代替:
for my $file ( glob($files) ) {
使用:
for my $file ( sort { (stat $b)[9] <=> (stat $a)[9] } glob($files) ) {
这将以相反的时间戳顺序排序,即第一个元素将是最新的。
您可能不想迭代与 glob 匹配的整个文件列表,只需使用最新的一个:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my $glob_pattern = './Project/chris/company/Delta/force/*/total/data.list';
my @files = ( sort { (stat $b)[9] <=> (stat $a)[9] } glob($glob_pattern) );
my $file = $files[0];
printf "%s: %i\n", $file, count_lines($file);
sub count_lines {
...
...
...
}
为什么(stat $b)[9]
和(stat $a)[9]
?因为修改时间是函数返回的13个元素列表中的第9号元素stat
。它的常用用法如下:
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
atime
、mtime
、 都是ctime
数值,自纪元(格林尼治标准时间 1970 年 1 月 1 日午夜)以来的秒数 - 即标准 unix time_t 值。因为它们是数字,所以可以像任何其他数字值一样对它们进行排序、比较、加法、减法等。
perldoc -f stat
有关 stat 函数的更多详细信息,请参阅 参考资料。
另请参阅perldoc -f sort
有关该sort
功能的详细信息。在上面的代码中,它使用代码块按从文件名派生的值(即它们的 mtimes)进行排序,而不是按文件名本身进行排序。
顺便说一句,请记住 perl 数组从 0 开始,而不是 1。因此 [9] 是第十个元素,从 0 开始。另外, [6] 是第七个元素,所以你(split('/',$_))[6]
可能应该[5]
代替[6]
。现在不需要,因为上面的代码使用文件的实际时间戳。
答案2
和zsh
:
wc -l < ./Project/chris/company/Delta/force/run_<->_df/total/data.list([-1])
data.list
将给出编号最高的行数run_..._df
。尽管
wc -l < ./Project/chris/company/Delta/force/run_<->_df/total/data.list(-om[1])
将给出最近修改的行数data.list
。
或者以数字方式对路径中找到的第一个数字序列进行O
排序:n
wc -l < ./Project/chris/company/Delta/force/*/total/data.list(nOe['
REPLY=${(MS)REPLY##<->}'][1])
1 从技术上讲,换行符,如果最后一个“行”没有分隔,这可能会给你一个与 perl 方法不同的数字。