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


136

我该如何做一个简单的find方法来排序最近修改过的结果?

这是find我正在使用的当前代码(我正在PHP中进行shell换码,因此这是变量的原因):

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

我如何才能按此顺序搜索最近修改过的内容?(请注意,我不希望它在搜索之后“排序”,而是根据最近修改的内容查找结果。)


github.com/shadkam/recentmost会做什么期望-但是需要构建它
user3392225

Answers:


150

用这个:

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

printf来自的论点man find

  • %Tk:文件的最后修改时间,格式为k

  • @:自1970年1月1日格林威治标准时间00:00开始的秒,含小数部分。

  • c:语言环境的日期和时间(1989年11月4日星期六,美国东部标准时间)。

  • %p:文件名。


5
+1非常有用,我找到的第一个答案是可读/有用的日期输出
Jake N

最可靠(且非常简单),因为时间被授予为数字顺序的(因此始终可以正确排序),谢谢!
水瓶座力量

1
我有这个别名来查找我的最近文件~/.zshrcfr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }它递归地查找所有包含传递给命令(fr <pattern>)的第一个参数的模式的文件,并对它们进行最后排序。
joelostblom

这很棒 !!!要与符号链接一起使用,请使用find -L ...
Varun Chandak

1
您可能想要ssed摆脱秒的小数部分,并像@PeterMortensen所示使用ISO8601:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty

83

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

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

如果您有GNU查找,请使其打印文件修改时间并以此排序。

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

如果您拥有GNU find,但没有其他GNU实用程序,则使用换行符作为分隔符,而不是null。您将失去对包含换行符的文件名的支持。

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个部分变得容易)。


我认为该find版本显示的是最旧的文件,因此您需要在中添加该-r选项sort
昆汀·普拉德

我的sed说它没有-z选项。
Kef Schecter

@KefSchecter然后使用换行符作为分隔符,但是您将失去对文件名中换行符的支持。
吉尔斯

以上是针对python2的。如果只有python3,则需要一些小的更改:python3 -c'import os,sys; times = {},用于sys.stdin.readlines()中的f:f = f [0:-1]; times [f] = os.stat(f).st_mtime for f in(sorted(times.keys(),key = lambda f:times [f],reverse = True))[:10]:print(f); '
尼尔·麦吉尔

40

您不需要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 (如果查找未实现“ -exec +”但知道“ -print0”,则优化速度)
  • find . -print|xargs command (如果参数中没有空格)

如果参数的主要部分由长路径,绝对路径或相对路径组成,则尝试将操作移至目录:cd /directory/with/long/path; command *另一个快速解决方案可能是匹配较少的参数:command [a-e]*; command [f-m]*; ...


1
如果文件很多,则会失败,并在ls上显示“参数列表太长”。
occulus 2012年

1
这是真的,但我相信这个问题是“我怎么做一个简单的发现......”
ЯрославРахматуллин

2
ls不会以xargs可以理解的方式引用文件名(没有-0选项,并且各种引用样式都不足够)
Tobu 2014年

10

你只需要ls

您可以find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;按照上述说明进行操作,

要么

ls -1rt `find /wherever/your/file/hides -type f`

2
如果文件很多,则会失败,并在ls上显示“参数列表太长”。也许重新使用xargs?
occulus 2012年

2
但是,如果多次xargs调用ls,排序将被破坏。
亚伦·D·马拉斯科

对于名称中带有空格的文件,此操作将失败。有什么建议吗?
user74094 '18

只是偶然发现了这个答案,而这正是我在类似情况下所需要的。问题:最后的作用是+;什么?如果没有,它似乎会给出相同的结果,;但是如果没有它,它将无法工作+
RocketNuts

这仅仅是另一个相同的答案公布前8个月,除部分有关使用“LS -1rt`找到...`”,这被打破
克莱门特

7

扩展user195696的答案

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个char表示1-9 GB,2个char表示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 按时间排序,这在这里无关紧要,但这就是我通常使用的时间。


1
注意:要改为按文件大小排序,只需在以上任一命令中将T@by 替换为即可s
Evgeni Sergeev 2014年

3

@ user195696答案的OS X变体:

  1. 带时间戳:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. 没有时间戳:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    

2

我发现这可以在Mac OS X上完成工作(并且通用性也足以在其他Unixen上工作):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort

2
可悲的是,这会在我的克罗地亚语设置中打印出本地化的月份名称,从而使排序不正确。
IvanVučica13年

user195696的答案适用于克罗地亚语设置(和其他设置)。
彼得·莫滕森

1

如果您的find选择非常简单,则可以不用它,而只需使用ls

ls -1 *.cc # -r -t optional

1

尝试:

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

但是用-mmin/ -mtime和过滤数据也很有用-type


1

采用:

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

我改进了此清单以处理文件名中的空格,请参见superuser.com/a/777007/134532
2014年1


0

我认为find没有任何选项可以修改输出顺序。 -mtime-mmin允许您将结果限制为在特定时间范围内已修改的文件,但不会对输出进行排序-您必须自己进行操作。GNU find有一个-printf选项,除其他外,它可以让您打印找到的每个文件的修改时间(格式为%t%Tk);这可能会帮助您按照所需find的方式对输出进行排序。


0

我通过使脚本正确处理文件名中的空格来改善了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

如果您想按时间订购所有PNG文件$PWD

这个简单的单行代码为regexp on find和on 提供了所有的灵活性ls

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less

0

您可以通过以下方式stat在BSD和Linux(而非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

sort | head按日期有一种干净而健壮的方法:

使用ls -l了漂亮的印刷

find . ! -type d -printf "%T@ %p\0" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.]\+ //' |
    xargs -0 ls -lt

作为函数:

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

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

Usage: findByDate [-h] [lines] [find options]

样品:

findByDate

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

即使在大文件系统树上,如xargs 已接收到的已排序列表一样,文件顺序也保持正确,即使ls必须运行多次。

findByDate -h 12

将列出按日期排序的另外12个最近的非目录,并以易于阅读的形式打印大小

findByDate 42 '-type l'

将会列出另外42个最近的符号链接

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

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

倒序

更换headtail和更改的开关sortls

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

功能相同,用法相同:

Usage: findByDate [-h] [lines] [find options]

-1

如果您只想获取每个项目的完整路径,则可以这样写下。

 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用于剪切每行的领先时间戳。


cut -d ' ' -f 2如果文件名包含空格,则将中断。
F.豪里

-3

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

之后cd到一个目录,使用

find . -iname "*" -ls


1
这不会按修改日期排序。
DavidPostill
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.