当单次调用的文件太多时,按时间对 ls 输出进​​行排序

当单次调用的文件太多时,按时间对 ls 输出进​​行排序

我知道我可以使用该选项ls按时间对输出进行排序-t

我知道,当我有太多文件以至于它们不适合一次ls调用时,我通常可以使用xargs(或find ... -exec ... {} +) 来ls多次调用。

我怎样才能将两者结合起来?我的文件数量超出了命令行的容纳范围,并且希望按时间排序列出它们。find . -type f -exec ls -t {} +不起作用,因为假设命令行上正好有 1000 个文件名,并且存在 3000 个文件,这将运行ls -t [first 1000 files]; ls -t [second 1000 files]; ls -t [last 1000 files],最后 1000 个文件find看到的修改时间很可能早于前 1000 个文件。似乎任何涉及xargs或等效的东西都有任何工作机会,似乎这种方法从根本上来说是有缺陷的,但我找不到一种方法工作。

答案1

ls -t其本身将按该排序列出当前目录中的所有文件,而根本不需要在命令行上列出它们。

如果您需要 的递归行为find,或者对文件进行一些其他测试,您可以find通过stat或 通过 GNUfind-printf选项生成带时间戳的条目并对其进行排序。就像是:

find . -type f -printf '%T@ %p\0' | sort -zn

-printf '%T@ %p\0'生成以 null 分隔的 Unix 时间戳 ( %T@)-文件名 ( %p) 对。sort -z也是一个非标准 GNU 扩展,它使用空分隔记录来保证文件名安全。sort大多数 BSD 也支持该选项,但-printf据我所知,仅限 GNU。

您可以将该输出剪切回仅文件名,或您喜欢的任何其他格式。

答案2

您可以findperlPosixly 一起使用:

$ find ! -name . -prune -print | perl -lne '
    $h{$_} = -M;
    END { print for sort {$h{$a} <=> $h{$b}} keys %h }
'

这假设您的文件名中没有换行符。

要处理换行符,您可以:

$ find ! -name . -prune -exec printf "%s\0" {} + | perl -0lne ...

或在您的代码中使用perl -lethen 。split /\0/,<>

答案3

在 zsh 中:

print -rl -- *(om)

全局限定符 om按修改时间对文件进行排序(按时间倒序排列,即最新的在前,如ls -t)。用于Om获得相反的顺序(时间顺序,如ls -tr)。使其*(Dom)包含点文件。

您当然可以改变图案,例如**/*(Dom)递归到子目录。如果要使用多个模式,请将它们放在括号中并使用|运算符分隔它们,例如*.(png|jpg)(om)

由于print是 shell 内置命令,因此该命令不受最大命令行长度限制的影响。如果你想调用外部命令批量、按顺序作用于文件,你就会遇到长度限制。printf '%s\0' *(om) | xargs -0 somecommand如果您的 xargs 支持空分隔输入(Linux、*BSD)或 zsh 自己的输入,则可以使用将文件提供给 xargszargs:

autoload -U zargs
zargs -r -e '' -- *(om) '' somecommand

要一次处理一个文件,请使用一个简单的循环,zsh 可以让您缩写该循环(csh 样式):

for x (*(om)) somecommand

相关内容