在进行递归调用时,ls似乎没有正确地对文件进行排序:

ls -altR . | head -n 3

如何在目录(包括子目录)中找到最近修改的文件?


当前回答

我发现上面的命令很有用,但对于我的情况,我需要查看文件的日期和时间,我有一个问题,几个文件的名称中有空格。 这是我的工作解决方案。

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l

其他回答

find . -type f -printf '%T@ %p\n' \
| sort -n | tail -1 | cut -f2- -d" "

对于一棵巨大的树,排序可能很难把所有东西都保存在内存中。

%T@像unix时间戳一样给出修改时间,sort -n按数字排序,tail -1取最后一行(最高时间戳),cut -f2 -d" "从输出中删除第一个字段(时间戳)。

编辑:就像-printf可能只在gnu中使用一样,ajreal中stat -c的使用也是如此。虽然在BSD上也可以做同样的事情,但格式化的选项是不同的(-f "%m %N"似乎是这样)

我错过了复数的部分;如果你想要更多的最新文件,只需要增加tail参数。

这将递归地将当前目录中所有目录的修改时间更改为每个目录中的最新文件:

for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done

在使用基于查找的解决方案多年之后,我发现自己希望能够排除像.git这样的目录。

我改用了这个基于rsync的解决方案。把这个放到~/bin/findlatest中:

#!/bin/sh
# Finds most recently modified files.
rsync -rL --list-only "$@" | grep -v '^d' | sort -k3,4r | head -5

现在是findlatest。将列出最近修改的5个文件,并查找latest—exclude .git。将列出。git中不包括的5个。

这是通过利用一些很少使用的rsync功能来实现的:“如果一个单一的源参数被指定为[rsync]而没有目的地,那么文件将以类似于ls -l的输出格式列出”(rsync手册页)。

与基于rsync的备份工具结合使用时,接受rsync参数的能力非常有用。例如,我使用rsnapshot,我用rsnapshot.conf行备份一个应用程序目录:

backup  /var/atlassian/application-data/jira/current/   home    +rsync_long_args=--archive --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"

rsync- excluded列出了我不想备份的目录:

- log/
- logs/
- analytics-logs/
- tmp/
- monitor/*.rrd4j

我现在可以看到最新的文件,将备份:

findlatest /var/atlassian/application-data/jira/current/ --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"

我一直在使用类似的东西,以及最近修改的文件的top-k列表。对于大型目录树,避免排序会快得多。如果是最近修改最多的文件:

find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'

在一个包含170万个文件的目录中,我在3.4秒内获得了最新的一个文件,与使用排序的25.5秒解决方案相比,速度提高了7.5倍。

接着@plundra的回答,下面是BSD和OS X版本:

find . -type f -print0 \
| xargs -0 stat -f "%m %N" \
| sort -rn | head -1 | cut -f2- -d" "