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

202 linux unix sorting find

我怎样才能做一个简单的find,通过最近修改的结果来排序?

这是find我正在使用的电流(我正在 PHP 中执行 shell 转义,所以这就是变量的原因):

find '$dir' -name '$str'\* -print | head -10
Run Code Online (Sandbox Code Playgroud)

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

小智 246

用这个:

find . -printf "%T@ %Tc %p\n" | sort -n
Run Code Online (Sandbox Code Playgroud)

printf论据来自man find

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

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

  • c: locale 的日期和时间(Sat Nov 04 12:02:33 EST 1989)。

  • %p: 文件名。

  • 请注意,对于 OSX,必须使用 GNU 版本“gfind”而不是“find”,因为“printf”不是“POSIX”“find”的一部分。可以使用“brew install findutils”来安装。 (8认同)
  • +1 非常有用,我找到的第一个答案是可读/有用的日期输出 (7认同)
  • 我有这个别名用于在我的 `~/.zshrc` 中查找最近的文件: `fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY % Tk:%TM %p\n" | 排序 -n | cut -d " " -f 2- | grep -i "$@" ; }` 它递归地查找包含传递给命令的第一个参数的模式的所有文件(`fr <pattern>`),并将它们与最新的最后一个排序。 (2认同)
  • 您可能想使用 `ssed` 去掉秒小数部分,并仍然使用 ISO8601,如@PeterMortensen 所示:`find 。 -type f -printf "%TY-%Tm-%TdT%TT %p\n" |排序-r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'​​` (2认同)

Gil*_*il' 90

最简单的方法是使用 zsh,这要归功于它的glob qualifiers

print -lr -- $dir/**/$str*(om[1,10])
Run Code Online (Sandbox Code Playgroud)

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

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

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

find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10
Run Code Online (Sandbox Code Playgroud)

如果你有 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];
    }'
Run Code Online (Sandbox Code Playgroud)

如果您有 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'
Run Code Online (Sandbox Code Playgroud)

在 PHP 中可能有一种方法可以做同样的事情,但我不知道。

如果您只想使用 POSIX 工具,那就比较复杂了;请参阅如何以递归方式列出按修改日期排序的文件(没有可用的 stat 命令!)(重新整理前 10 个是简单的部分)。


Яро*_*лин 50

你不需要 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 "{}" +;
Run Code Online (Sandbox Code Playgroud)

如果命令 * 以失败状态退出(即参数列表太长),那么您可以使用 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]*; ...

  • 如果有很多文件,这将失败并在 ls 上显示“参数列表太长”。 (2认同)
  • ls 不会以 xargs 可以理解的方式引用文件名(没有 -0 选项,并且各种引用样式都不合适) (2认同)

Evg*_*eev 13

扩展user195696 的回答

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-
Run Code Online (Sandbox Code Playgroud)

对于每个文件,这首先输出数字时间戳(用于排序,然后是制表\t),然后是人类可读的时间戳,然后是文件大小(不幸的是find's-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
Run Code Online (Sandbox Code Playgroud)

我特意将文件大小字段设置为 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 {}
Run Code Online (Sandbox Code Playgroud)

给出如下输出:

-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
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • -I{}导致的发生{}通过一个参数来代替,换行符现在都是参数隔板(注意以上文件名中的空格)。

  • ls -G 禁止打印组名(浪费空间)。

  • ls -h --si生成人类可读的文件大小(使用 更正确--si)。

  • ls -t 按时间排序,这在这里无关紧要,但这是我通常使用的。


小智 11

你只需要ls

你可以find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;按照上面说的做,

或者

ls -1rt `find /wherever/your/file/hides -type f`
Run Code Online (Sandbox Code Playgroud)

  • 但是如果`xargs` 多次调用`ls`,排序就会被破坏。 (4认同)
  • 如果有很多文件,这将失败并在 ls 上显示“参数列表太长”。也许重新使用xargs? (3认同)

小智 8

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

find . -type f -exec ls -t {} +
Run Code Online (Sandbox Code Playgroud)

  • 这应该是最好的答案。简单,容易理解。关键是最后的加号。这允许“find”仅调用“ls”一次。 (3认同)

use*_*399 5

@ user195696 答案的 OS X 变体:

  1. 带时间戳:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
    Run Code Online (Sandbox Code Playgroud)
  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) }'
    
    Run Code Online (Sandbox Code Playgroud)


小智 2

尝试:

find '$dir' -name '$str'\* -print | xargs ls -tl | head -10
Run Code Online (Sandbox Code Playgroud)

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


归档时间:

查看次数:

251007 次

最近记录:

4 年,6 月 前