操作系统:Linux 文件系统类型:ext3 首选解决方案:Bash(脚本/一行程序)、Ruby或Python

我有几个目录,其中有几个子目录和文件。我需要列出所有这些目录,其构造方式是将每个一级目录列在其中最新创建/修改文件的日期和时间旁边。

为了说明这一点,如果我接触一个文件或修改它的内容向下几级子目录,该时间戳应该显示在第一级目录名旁边。假设我有一个这样的目录:

./alfa/beta/gamma/example.txt

我修改了文件example.txt的内容,我需要在第一级目录alfa旁边以人类可读的形式显示时间,而不是epoch。我已经尝试了一些使用find, xargs, sort和类似的东西,但我不能绕过“alfa”的文件系统时间戳不改变的问题,当我创建/修改文件的几个级别。


当前回答

下面是一个版本,它可以处理包含空格、换行符和glob字符的文件名:

find . -type f -printf "%T@ %p\0" | sort -zk1nr

找到……-printf打印文件修改时间(Epoch值),后面跟着空格和以\0结尾的文件名。 sort -zk1nr读取以NUL终止的数据,并对其反向排序

由于问题被标记为Linux,我假设GNU核心实用程序是可用的。

你可以用下面的管道:

xargs -0 printf "%s\n"

打印以换行符结束的按修改时间(最近的第一个)排序的修改时间和文件名。

其他回答

这篇文章中的Perl和Python解决方案帮助我解决了Mac OS X上的这个问题:

如何递归地列出按修改日期排序的文件(没有可用的stat命令!)

引自帖子:

Perl:

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

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]): print f'

我显示的是最新的访问时间,你可以很容易地修改它来做最新的修改时间。

有两种方法:


If you want to avoid global sorting which can be expensive if you have tens of millions of files, then you can do (position yourself in the root of the directory where you want your search to start): Linux> touch -d @0 /tmp/a; Linux> find . -type f -exec tcsh -f -c test `stat --printf="%X" {}` -gt `stat --printf="%X" /tmp/a` ; -exec tcsh -f -c touch -a -r {} /tmp/a ; -print The above method prints filenames with progressively newer access time and the last file it prints is the file with the latest access time. You can obviously get the latest access time using a "tail -1". You can have find recursively print the name and access time of all files in your subdirectory and then sort based on access time and the tail the biggest entry: Linux> \find . -type f -exec stat --printf="%X %n\n" {} \; | \sort -n | tail -1

现在你知道了……

@anubhava的回答很好,但不幸的是,它不能在BSD工具上工作——也就是说,它不能与macOS上默认安装的find一起工作,因为BSD find没有-printf操作符。

所以这里有一个变体,适用于macOS + BSD(在我的Catalina Mac上测试),它结合了BSD find与xargs和stat:

$ find . -type f -print0 \
      | xargs -0 -n1 -I{} stat -f '%Fm %N' "{}" \
      | sort -rn 

当我在这里时,这里是我喜欢使用的BSD命令序列,它将时间戳设置为ISO-8601格式

$ find . -type f -print0 \
    | xargs -0 -n1 -I{} \
       stat  -f '%Sm %N' -t '%Y-%m-%d %H:%M:%S' "{}" \
    | sort -rn

(注意,与@anubhava的答案不同,我的答案将文件名从find传递给xargs作为单个参数,而不是以\0终止的列表,这将改变在最后输出的内容)

下面是GNU版本(即@anubhava的答案,但是iso-8601格式):

$ gfind . -type f -printf "%T+ %p\0" | sort -zk1nr

相关问:查找缺少选项-printf,现在怎么办?

对于那些面对的人

stat: unrecognized option: format

当执行Heppo的答案(查找$1 -type f -exec stat——format '%Y:% Y %n' "{}" \;| sort -nr | cut -d: -f2- | head)

请尝试使用-c键来替换——format,最后调用将是:

find $1 -type f -exec stat -c '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

这在一些Docker容器中为我工作,在那里stat不能使用——format选项。

Bash有一行脚本解决方案,如何递归地在多个目录中查找最新修改的文件。请找到以下命令与您的目标目录。

 ls -ltr $(find /path/dir1 /path/dir2 -type f)

对于今天,grep今天的日期或时间如下面的命令所述

 (ls -ltr $(find /path/dir1 /path/dir2 -type f)) |grep -i 'Oct 24'