如何以递归方式查找并列出目录中最新修改的文件(包括子目录和时间)
- 2024-10-21 09:14:00
- admin 原创
- 76
问题描述:
操作系统:Linux
文件系统类型:ext3
首选解决方案:Bash(脚本/单行程序)、Ruby 或 Python
我有多个目录,其中包含多个子目录和文件。我需要列出所有这些目录,列表的构建方式是,每个一级目录都列在其中最新创建/修改文件的日期和时间旁边。
需要澄清的是,如果我修改了某个文件或修改了其在下一级子目录中的内容,则该时间戳应显示在第一级目录名称旁边。假设我有一个结构如下的目录:
./alfa/beta/gamma/example.txt
并且我修改了文件的内容example.txt
,我需要以人类可读的形式(而不是纪元)显示在第一级目录旁边的时间alfa
。我尝试使用 find、xargs
等sort
方法,但我无法解决在创建/修改几级以下的文件时“alfa”的文件系统时间戳不会改变的问题。
解决方案 1:
尝试一下这个:
#!/bin/bash
find $1 -type f -exec stat --format '%Y :%y %n' "{}" ; | sort -nr | cut -d: -f2- | head
使用它应该开始递归扫描的目录的路径执行它(它支持带空格的文件名)。
如果文件很多,可能需要一段时间才能返回任何内容。如果我们改用xargs
以下方法,则可以提高性能:
#!/bin/bash
find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head
这稍微快一点。
解决方案 2:
查找文件状态最后更改于N分钟之前的所有文件:
find -cmin -N
例如:
find -cmin -5
使用-ctime
代替-cmin
几天:
find -ctime -3
在 FreeBSD 和 MacOS 上:您还可以使用-ctime n[smhdw]
秒、分钟、小时、天和周。如果没有提供单位,则默认为天。
例子:
# FreeBSD and MacOS only:
find . -ctime -30s
find . -ctime -15
find . -ctime -52w
解决方案 3:
GNU find(参见man find
)有一个-printf
参数,用于显示 Epoch mtime 中的文件和相对路径名。
redhat> find . -type f -printf '%T@ %P
' | sort -n | awk '{print $2}'
解决方案 4:
我把Daniel Böhmer 的精彩回答简化为一句话:
stat --printf="%y %n
" $(ls -tr $(find * -type f))
如果文件名中有空格,可以使用此修改:
OFS="$IFS";IFS=$'
';stat --printf="%y %n
" $(ls -tr $(find . -type f));IFS="$OFS";
解决方案 5:
尝试一下:
#!/bin/bash
stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1)
它用于find
从目录中收集所有文件,ls
按修改日期排序列出它们,head
选择第一个文件,最后stat
以良好的格式显示时间。
目前,文件名中包含空格或其他特殊字符的文件并不安全。如果它还不能满足您的需求,请写一条评论。
解决方案 6:
这是我正在使用的(非常高效):
function find_last () { find "${1:-.}" -type f -printf '%TY-%Tm-%Td %TH:%TM %P
' 2>/dev/null | sort | tail -n "${2:-10}"; }
优点:
无论扫描多少文件,它只会生成 3 个进程
适用于包含空格的文件名
适用于大量文件
用法:
find_last [dir [number]]
在哪里:
dir
- 要搜索的目录 [当前目录]number
- 显示最新文件的数量 [10]
输出find_last /etc 4
如下:
2019-07-09 12:12 cups/printers.conf
2019-07-09 14:20 salt/minion.d/_schedule.conf
2019-07-09 14:31 network/interfaces
2019-07-09 14:41 environment
解决方案 7:
此命令适用于 Mac OS X:
find "$1" -type f -print0 | xargs -0 gstat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head
在 Linux 上,正如原始海报所要求的那样,使用stat
而不是gstat
。
当然,这个答案是user37078的杰出解决方案,从评论提升为完整答案。我结合了CharlesB的见解,以便gstat
在 Mac OS X 上使用。顺便说一句,我从MacPorts而不是Homebrew获得了coreutils 。
以下是我将其打包成简单命令~/bin/ls-recent.sh
以便重复使用的方法:
#!/bin/bash
# ls-recent: list files in a directory tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
#
# Where "path" is a path to target directory, "-10" is any argument to pass
# to "head" to limit the number of entries, and "more" is a special argument
# in place of "-10" which calls the pager "more" instead of "head".
if [ "more" = "$2" ]; then
H=more; N=''
else
H=head; N=$2
fi
find "$1" -type f -print0 |xargs -0 gstat --format '%Y :%y %n' \n |sort -nr |cut -d: -f2- |$H $N
解决方案 8:
忽略隐藏文件 — 带有快速准确的时间戳
以下是如何在包含子目录的目录中查找和列出最新修改的文件。隐藏文件会被故意忽略。而文件名中的空格处理得很好——但你不应该使用它们!时间格式可以自定义。
$ find . -type f -not -path '*/.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p
' |sort -nr |head -n 10
2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht
find
点击链接即可找到更多内容。
解决方案 9:
这篇文章中的 Perl 和 Python 解决方案都帮助我在 Mac OS X 上解决了这个问题:
如何递归列出按修改日期排序的文件(没有可用的 stat 命令!)
引用该帖子:
Perl:
find . -type f -print |
perl -l -ne '
$_{$_} = -M; # store file age (mtime - now)
END {
$,="
";
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'
解决方案 10:
这是一个适用于可能包含空格,换行符和 glob 字符的文件名的版本:
find . -type f -printf "%T@ %p " | sort -zk1nr
find ... -printf
打印文件修改时间(Epoch 值),后跟空格和