如何列出第 n 个最年轻的文件(不解析 ls!)

如何列出第 n 个最年轻的文件(不解析 ls!)

所以我知道解析 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对列表进行排序,最后headtail获取所需的编号文件名:

find . -maxdepth 1 -type f -printf '%T@ %p\n' | sort -k1,1nr | head -5 | tail -1

答案4

一种方法是(假设文件名中没有换行符)

ls -t ... | head -n5 | tail -n1

相关内容