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

djs*_*ide 4 ls bash

所以我知道解析 ls 很糟糕!.

今天我发现了这个金块:

FILENAME=`ls -t $READ_FOLDER | head -1`
Run Code Online (Sandbox Code Playgroud)

所以我相信最初这是为了获取最新的文件名,我实际上现在想要调整它,获取可能是第 5 个最新文件,因为检查它的过程有点慢,所以我们不能确定他们已经尚未处理。

我正在使用 bash,但也不反对 sh 通用解决方案。

Sob*_*que 8

过分地:

#!/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";
}
Run Code Online (Sandbox Code Playgroud)

减少到:

perl -e '%f = map { $_ => (stat)[9] } glob("./*");print "" . ( sort { $f{$b} <=> $f{$a} } keys %f )[4];'
Run Code Online (Sandbox Code Playgroud)

其中第“N”个文件是 4,因为 perl 数组从零开始。


ter*_*don 6

假设您可以访问 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
Run Code Online (Sandbox Code Playgroud)

因此,第 5 个最新文件是file5. 要打印它,您可以执行以下操作:

$ stat --printf '%Y %n\0' * | sort -zrnk1 | 
    awk -vRS='\0' 'NR==5{sub(/^[^ ]* /,"",$0); print}'
Run Code Online (Sandbox Code Playgroud)

然后,您可以轻松地将它变成一个 shell 函数,该函数可以将 N(在您的示例中为 5)作为参数。只需将这些行添加到您的~/.bashrc或等效的:

nthfile() {
  stat --printf '%Y %n\0' * | sort -zrnk1 |
     awk -vRS='\0' -vn="$1" 'NR==n{sub(/^[^ ]* /,"",$0); print}'
}
Run Code Online (Sandbox Code Playgroud)

请注意,这还将向您显示目录。如果您需要它来匹配隐藏文件以及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: 替换从行首 ( ^[^ ]*) 到第一个空格的所有非空格字符并打印结果