![Unix/Linux 按修改日期查找和排序](https://linux22.com/image/1278806/Unix%2FLinux%20%E6%8C%89%E4%BF%AE%E6%94%B9%E6%97%A5%E6%9C%9F%E6%9F%A5%E6%89%BE%E5%92%8C%E6%8E%92%E5%BA%8F.png)
我怎样才能做一个简单的事情find
来按最近修改的时间对结果进行排序?
这是我当前find
正在使用的(我正在 PHP 中进行 shell 转义,所以这就是变量的原因):
find '$dir' -name '$str'\* -print | head -10
我怎样才能按照最近修改的顺序进行搜索?(请注意,我不希望它在搜索“之后”进行排序,而是根据最近修改的内容查找结果。)
答案1
用这个:
find . -printf "%T@ %Tc %p\n" | sort -n
printf
来自的论点man find
:
%Tk
:文件的最后修改时间,格式以 为准k
。@
:自 1970 年 1 月 1 日 00:00 GMT 以来的秒数,包含小数部分。c
:语言环境的日期和时间(1989 年 11 月 4 日星期六 12:02:33 EST)。%p
:文件的名称。
答案2
最简单的方法是使用 zsh,因为它glob 限定符。
print -lr -- $dir/**/$str*(om[1,10])
如果您有 GNU find,请让它打印文件修改时间并按此排序。
find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10
如果您有 GNU find 但没有其他 GNU 实用程序,请使用换行符作为分隔符而不是空值;您将失去对包含换行符的文件名的支持。
find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10
如果您有 Perl(这里我假设文件名中没有换行符):
find . -type f -print |
perl -l -ne '
$_{$_} = -M; # store file age (mtime - now)
END {
$,="\n";
@sorted = sort {$_{$a} <=> $_{$b}} keys %_; # sort by increasing age
print @sorted[0..9];
}'
如果您有 Python(也假设文件名中没有换行符):
find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print(f)'
在 PHP 中可能有办法做同样的事情,但我不知道。
如果你只想使用 POSIX 工具,那就比较复杂了;请参阅如何递归列出按修改日期排序的文件(没有可用的 stat 命令!)(保留前 10 个是比较容易的部分)。
答案3
你不需要 PHP 或 Python,只需ls:
man ls:
-t sort by modification time
-r, reverse order while sorting (--reverse )
-1 list one file per line
find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;
如果命令*以失败状态退出(即参数列表太长),然后你可以用 find 进行迭代。转述自:新进程的最大参数长度
find . -print0|xargs -0 command
(优化速度,如果 find 没有实现“-exec +”但知道“-print0”)find . -print|xargs command
(如果参数中没有空格)
如果参数的主要部分由长、绝对或相对路径组成,那么尝试将您的操作移动到目录中:cd /directory/with/long/path; command *
另一个快速修复可能是匹配更少的参数:command [a-e]*; command [f-m]*; ...
2023 年更新
xargs 解决方案实际上不起作用,因为它将分几批输出,因此您会在每批中找到最新的文件,而不是所有的最新文件。
在我的本地 bin 仓库:
转载于此:
#!/bin/bash
function strip_1() { awk ' BEGIN{ RS="\0"} { $1="" ; gsub(/^\s/,"", $0); print }'; }
function strip_1n() { awk '{ $1="" ; gsub(/^\s/,"", $0); print }'; }
function n2z() { tr \\n \\0; }
find=/usr/bin/find
if [[ $0 == *latest0 ]]; then
$find ${1:-./} -not -path '*/.git/*' -type f -printf "%T@ %p\0" | sort -nz | n2z | strip_1 | n2z
else
$find ${1:-./} -not -path '*/.git/*' -type f -printf "%T@ %p\n" | sort -n | strip_1n
fi
答案4
扩展用户195696 的回答:
find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-
对于每个文件,首先输出数字时间戳(用于排序,然后进行制表\t
),然后输出人类可读的时间戳,然后输出文件大小(不幸的是,find
不能-printf
以兆字节为单位,只能以千字节为单位),然后输出带有相对路径的文件名。
然后sort -n
按第一个数字字段对其进行排序。
然后cut
删除用户不感兴趣的第一个数字字段。(打印第二个字段。)默认字段分隔符是\t
或制表符。
输出示例:
Thu 06 Feb 2014 04:49:14 PM EST 64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST 0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST 64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST 0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST 64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST 9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST 9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST 9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST 32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST 0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST 64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST 70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST 70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST 70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST 0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST 32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST 224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST 32 KiB ./plot_grid.m
我故意将文件大小字段设为 6 个字符,因为如果将其设得更长,则很难从视觉上区分文件的大小。这样,大于 1e6 KiB 的文件就会凸显出来:1 个字符表示 1-9 GB,2 个字符表示 10-99 GB,等等。
编辑:这是另一个版本(因为find . -printf "%Tc"
在 MinGW/MSYS 上崩溃):
find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}
给出如下输出:
-rw-r--r-- 1 es 23K Jul 10 2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png
在哪里:
-I{}
导致的发生{}
被一个参数所取代,和换行符现在是参数分隔符(请注意上面文件名中的空格)。ls -G
禁止打印组名(浪费空间)。ls -h --si
生成人类可读的文件大小(使用 更正确--si
)。ls -t
按时间排序,这与此无关,但这是我通常使用的。