![如何列出第 n 个最年轻的文件(不解析 ls!)](https://linux22.com/image/73077/%E5%A6%82%E4%BD%95%E5%88%97%E5%87%BA%E7%AC%AC%20n%20%E4%B8%AA%E6%9C%80%E5%B9%B4%E8%BD%BB%E7%9A%84%E6%96%87%E4%BB%B6%EF%BC%88%E4%B8%8D%E8%A7%A3%E6%9E%90%20ls%EF%BC%81%EF%BC%89.png)
所以我知道解析 ls 是坏的!。
今天我发现了这个金块:
FILENAME=`ls -t $READ_FOLDER | head -1`
所以我相信最初这是为了获取最新的文件名而设计的,我实际上现在想调整它,以获取也许第五名最新的文件,因为检查它的过程有点慢,所以我们无法确定它们是否已被处理。
我正在 bash 中工作,但也不反对 sh 通用解决方案。
答案1
珀里斯利:
#!/usr/bin/env perl
use strict;
use warnings;
my %files_by_mtime;
foreach my $file ( glob ( "./*" ) ) {
my ( $mtime ) = (stat($file))[9];
$files_by_mtime{$file} = $mtime;
}
foreach my $f ( sort { $files_by_mtime{$b} <=> $files_by_mtime{$a} } keys %files_by_mtime ) {
print "$f $files_by_mtime{$f}\n";
}
减少到:
perl -e '%f = map { $_ => (stat)[9] } glob("./*");print "" . ( sort { $f{$b} <=> $f{$a} } keys %f )[4];'
其中第“N”个文件是 4,因为 perl 数组从零开始。
答案2
假设您可以访问 GNU 工具(如果您运行的是 Linux,则可以),我会使用它stat
。例如:
$ ls -l
total 0
-rw-r--r-- 1 terdon terdon 0 Sep 15 16:49 file1
-rw-r--r-- 1 terdon terdon 0 Sep 15 16:39 file2
-rw-r--r-- 1 terdon terdon 0 Sep 15 16:29 file3
-rw-r--r-- 1 terdon terdon 0 Sep 15 16:19 file4
-rw-r--r-- 1 terdon terdon 0 Sep 15 16:09 file5
-rw-r--r-- 1 terdon terdon 0 Sep 15 15:59 file6
-rw-r--r-- 1 terdon terdon 0 Sep 15 15:49 file7
因此,第五个最新文件是file5
.要打印该内容,您可以执行以下操作:
$ stat --printf '%Y %n\0' * | sort -zrnk1 |
awk -vRS='\0' 'NR==5{sub(/^[^ ]* /,"",$0); print}'
然后,您可以轻松地将其放入 shell 函数中,该函数可以将 N(在您的示例中为 5)作为参数。只需将这些行添加到您的~/.bashrc
或同等内容中:
nthfile() {
stat --printf '%Y %n\0' * | sort -zrnk1 |
awk -vRS='\0' -vn="$1" 'NR==n{sub(/^[^ ]* /,"",$0); print}'
}
请注意,这还将显示目录。如果您需要它来匹配隐藏文件,请shopt -s dotglob
在上述命令之前运行(假设您使用的是 bash)。
解释
stat --printf '%Y %n\0' *
:对于当前文件夹中的每个文件或目录,打印自纪元 ( ) 以来的修改日期(以秒为单位%s
)和文件名 ( ),并以 代替%n
结束每行。这使我们能够正确处理包含换行符的文件名。\0
\n
sort -zrnk1
:按逆序 (-r
) 对输出进行排序,从最新到最旧。告诉-z
我们sort
期待空终止的输入行。告诉-n
它按数字排序,并且-k1
在排序时仅考虑第一个字段。awk
:-vRS='\0'
:设置输入记录(行)分隔符为\0
;vn=$1
:将变量设置n
为作为函数输入给出的任何值;NR==n{}
:仅在线运行n
(第一个示例中的 5);sub(/^[^ ]* /,"",$0); print
:替换从行首 (^[^ ]*
) 到第一个空格的所有非空格字符并打印结果
答案3
您可以使用 GNUfind
列出修改时间以纪元时间表示的文件,然后使用sort
对列表进行排序,最后head
并tail
获取所需的编号文件名:
find . -maxdepth 1 -type f -printf '%T@ %p\n' | sort -k1,1nr | head -5 | tail -1
答案4
一种方法是(假设文件名中没有换行符)
ls -t ... | head -n5 | tail -n1