我知道我可以使用该选项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
您可以find
与perl
Posixly 一起使用:
$ 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 -le
then 。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