2011-06-07 18:23:57 +0000 2011-06-07 18:23:57 +0000
152
152

Unix/Linux按修改日期查找和排序。

我怎样才能做一个简单的find,使结果按最近修改的时间排序?

这是我目前使用的find (我在PHP中做了一个shell escape,所以这就是变量的原因)。

find '$dir' -name '$str'\* -print | head -10

怎样才能让搜索顺序按最近修改的时间排序?(注意,我不想让它在搜索之后排序,而是根据最近修改的内容来查找结果。)

答案 (17)

168
168
168
2013-02-05 13:31:01 +0000

用这个。

find . -printf "%T@ %Tc %p\n" | sort -n

printf参数来自 man find

  • %Tk.文件的最后修改时间,格式由k指定。文件的最后修改时间,格式由 @指定。

  • c: 自 1970 年 1 月 1 日格林尼治标准时间 00:00 起的秒数,带小数部分。

  • %p: 本地的日期和时间 (Sat Nov 04 12:02:33 EST 1989)。

  • 0x6&: 文件名。

85
85
85
2011-06-07 18:39:34 +0000

最简单的方法是使用zsh,由于它的 glob限定符

print -lr -- $dir/**/$str*(om[1,10])

如果你有GNU find,让它打印文件修改时间,并以此排序。

find -type f -printf '%T@ %p```
find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^]* //' | head -n 10
```' |
sort -zk 1nr |
sed -z 's/^[^]* //' | tr '```
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];
    }'
```' '\n' | head -n 10

如果你有GNU find,但没有其他GNU工具,请使用换行符作为分隔符而不是空字符;你将失去对包含换行符的文件名的支持。

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'

如果你有Perl (这里我假设文件名中没有换行符):

0x1&

如果你有Python (同样假设文件名中没有换行符):

0x1&

在PHP中可能也有同样的方法,但我不知道。

如果你只想用POSIX工具工作,那就比较复杂了;请看 如何按修改日期递归排序的文件列表 (没有 stat 命令可用!) (重排前 10 个是简单的部分)。

41
41
41
2011-06-16 18:11:00 +0000

你不需要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]*; ...

10
10
10
2012-05-18 07:58:06 +0000

你只需要 ls

你可以做find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;,如上所述,

ls -1rt `find /wherever/your/file/hides -type f`
```。
8
8
8
2014-04-24 08:12:01 +0000

扩展 user195696 的回答 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

对于每一个文件,首先输出数字时间戳(用于排序,然后是制表\t),然后是一个人类可读的时间戳,然后是文件大小(不幸的是find-printf不能以mebibytes为单位,只能以kibibytes为单位),然后是文件名和相对路径。

然后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 按时间排序,这在这里无关紧要,但这是我通常使用的方法。

4
4
4
2016-02-24 15:18:34 +0000

OS X版本的@user195696的答案。

1.有时间戳:

  1. 没有时间戳。
2
2
2
2019-03-12 19:32:27 +0000

我有一个适用于FreeBSD (OS X) 和Linux的简单解决方案:

find . -type f -exec ls -t {} +
```。
2
2
2
2012-07-26 07:42:44 +0000

我发现这在Mac OS X上完成了工作(并且通用于在其他Unixen上也能工作):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
```。
1
1
1
2013-12-08 09:14:14 +0000

使用:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

该命令将按修改日期对文件进行排序。

并显示出这样的结果。

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
1
1
1
2014-05-02 11:16:59 +0000

如果你的find选择非常简单,你也许可以不用它,只用ls

ls -1 *.cc # -r -t optional
0
0
0
2014-07-04 14:58:50 +0000

我改进了Akashs的答案,让脚本正确处理文件名中的空格。

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
0
0
0
2019-09-11 08:23:43 +0000

使用sort | head进行漂亮的打印

find . ! -type d -printf "%T@ %p```
findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zrn |
        head -zn ${1:--0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dlt${humansize}
}
```" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.] //' |
    xargs -0 ls -lt

作为一个 bash 函数。

findByDate

这可以通过一个或两个参数来运行,甚至可以不使用:

findByDate -h 12

示例:

findByDate 42 '-type l'

将列出所有按日期排序的非目录。注意:

即使在大的文件系统树上,由于ls -l收到的是已经排序的列表,即使xargs必须运行很多次,文件顺序也会保持正确。

findByDate -0 '( -type l -o -type b -o -type s -o -type c )'

将列出12个按日期排序的最新的非目录,大小以人类可读_的形式打印出来

findByDate() {
    local humansize=''
    ["$1" = "-h"] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p```
Usage: findByDate [-h] [lines] [find options]
```" |
        sort -zn |
        tail -zn ${1:-+0} |
        sed -z 's/^[0-9.] //' |
        xargs -0 ls -dltr${humansize}
}

将列出42个最新的符号链接

0x1&

将列出所有符号链接、块设备、套接字和字符设备,按日期排序。

反转顺序

ls 取代 head,并更改 tailsort 的开关。

0x1&

功能相同,用法相同。

0x1&

0
0
0
2011-06-07 18:33:10 +0000

我不认为find有任何修改输出排序的选项。-mtime-mmin会让你把结果限制在某个时间窗口内修改过的文件,但输出不会排序–你得自己去做。GNU find有一个-printf选项,除此之外,它还可以让你打印出每个找到的文件的修改时间(格式字符串%t%Tk);这可能会帮助你按照你的意愿对find的输出进行排序。

0
0
0
2018-06-24 23:33:20 +0000

你可以在BSD和Linux上以这种方式使用stat(在POSIX上不行)。

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

如果你想限制数量:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
```。
0
0
0
2014-05-17 10:55:57 +0000

如果你想把所有的PNG文件按时间排序,在$PWD

这个简单的单线程给了findls上所有regexp的灵活性。

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
-1
-1
-1
2017-03-28 01:13:40 +0000

如果你只想得到每个项目的完整路径,你可以这样写。

find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

其中 -printf “%T@ %p\n ” 表示给出排序标准(日期), ‘sort -nr’ 表示按日期排序, head -10 表示列出前 10 个结果, cut -d ‘ ’ -f 2 表示剪掉每行的前导时间戳。

-3
-3
-3
2017-03-25 09:09:59 +0000

我有一个简单的解决方案。

cd到一个目录后,用

find . -iname "*" -ls