操作系统:Linux
文件系统类型:ext3
首选解决方案:bash(script / oneliner),ruby,python
我有几个目录,里面有几个子目录和文件。我需要列出所有这些目录,这些目录的构造方式使得每个第一级目录都列在其中最新创建/修改文件的日期和时间旁边。
为了澄清,如果我触摸文件或将其内容修改为几个子目录级别,那么该时间戳应该显示在第一级目录名称旁边。假设我有一个像这样的结构目录:
./alfa/beta/gamma/example.txt
我修改了文件example.txt
的内容,我需要以人类可读形式显示在第一级目录alfa
旁边的时间,而不是epoch。我已经尝试了一些使用find,xargs
,sort
之类的东西,但是当我创建/修改文件时,我无法解决'alfa'的文件系统时间戳没有改变的问题几级下来。
答案 0 :(得分:430)
试试这个:
#!/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
这有点快。
答案 1 :(得分:169)
要查找文件状态上次更改的所有文件 N 分钟前:
find -cmin -N
例如:
find -cmin -5
答案 2 :(得分:37)
GNU Find(请参阅man find
)有一个-printf
参数,用于显示文件EPOCh时间和相对路径名。
redhat> find . -type f -printf '%T@ %P\n' | sort -n | awk '{print $2}'
答案 3 :(得分:33)
我缩短了光环对这个单线的真棒答案
stat --printf="%y %n\n" $(ls -tr $(find * -type f))
已更新:如果文件名中有空格,则可以使用此修改
OFS="$IFS";IFS=$'\n';stat --printf="%y %n\n" $(ls -tr $(find . -type f));IFS="$OFS";
答案 4 :(得分:13)
试试这个
#!/bin/bash
stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1)
使用find
收集目录中的所有文件,ls
列出按修改日期排序的文件,head
选择第一个文件,最后stat
显示时间很好。
目前,名称中包含空格或其他特殊字符的文件不安全。如果它还不能满足您的需求,请写一个表扬。
答案 5 :(得分:10)
此命令适用于Mac OS X:
find "$1" -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head
在Linux上,正如原始海报所问,使用stat
代替gstat
。
这个答案当然是user37078出色的解决方案,从评论到完整答案。我在CharlesB的洞察力中混合了在Mac OS X上使用gstat
。顺便说一句,我从MacPorts而不是homebrew获得 coreutils
以下是我将其打包成一个简单的命令~/bin/ls-recent.sh
以供重用:
#!/bin/bash
# ls-recent: list files in a dir tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
#
# Where "path" is a path to target directory, "-10" is any arg to pass
# to "head" to limit the number of entries, and "more" is a special arg
# 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' \
|sort -nr |cut -d: -f2- |$H $N
答案 6 :(得分:5)
这篇文章中的perl和Python解决方案都帮助我在Mac OS X上解决了这个问题:https://unix.stackexchange.com/questions/9247/how-to-list-files-sorted-by-modification-date-recursively-no-stat-command-avail。
从帖子中引用:
的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'
答案 7 :(得分:3)
我正在显示最新的访问时间,您可以轻松修改它以执行最新的模拟时间。
有两种方法可以做到这一点:
1)如果你想避免全局排序,如果你有数千万个文件,这可能会很昂贵,那么你可以这样做:(将你自己置于你希望搜索开始的目录的根目录中)
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
上述方法打印文件名的访问时间越来越长,打印的最后一个文件是具有最新访问时间的文件。显然,您可以使用“tail -1”获取最新的访问时间。
2)您可以找到递归打印名称,访问子目录中所有文件的时间,然后根据访问时间和尾部排序最大的条目:
linux> \find . -type f -exec stat --printf="%X %n\n" {} \; | \sort -n | tail -1
你有它......
答案 8 :(得分:3)
我在我的.profile中有这个别名,我经常使用
$ alias | grep xlogs
xlogs='sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R'
所以它可以满足您的需求(除了它不会遍历更改多个级别的日期/时间) - 查找最新文件(在这种情况下为* .log和* .trc文件);它也只查找在最后一天修改的文件,然后按时间排序并通过less输出管道输出:
sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R
PS。注意我在某些服务器上没有root,但总是有sudo,所以你可能不需要那个部分。
答案 9 :(得分:2)
很好地处理文件名中的空格 - 而不是你应该使用它们!
$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10
2017.01.28 07h00 Sat ./recent
2017.01.21 10h49 Sat ./hgb
2017.01.16 07h44 Mon ./swx
2017.01.10 18h24 Tue ./update-stations
2017.01.09 10h38 Mon ./stations.json
可以通过链接找到
答案 10 :(得分:1)
@anubhava's answer 很棒,但不幸的是不能在 BSD 工具上工作——即它不能与 find
that comes installed by default on macOS 一起工作,因为 BSD find
没有 {{1 }} 运算符。
所以这里有一个适用于 macOS + BSD 的变体(在我的 Catalina Mac 上测试过),它结合了 BSD -printf
与 xargs 和 stat
:
find
当我在这里时,这是我喜欢使用的 BSD 命令序列,它将时间戳放在 ISO-8601 format 中
$ find . -type f -print0 \
| xargs -0 -n1 -I{} stat -f '%Fm %N' "{}" \
| sort -rn
(请注意,与@anubhava 不同,我的两个答案都将文件名从 $ find . -type f -print0 \
| xargs -0 -n1 -I{} \
stat -f '%Sm %N' -t '%Y-%m-%d %H:%M:%S' "{}" \
| sort -rn
传递到 find
作为单个参数而不是 xargs
终止列表,这会改变输出的内容最后)
这是 GNU 版本(即@anubhava 的答案,但采用 iso-8601 格式):
\0
答案 11 :(得分:1)
快速重击功能:
# findLatestModifiedFiles(directory, [max=10, [format="%Td %Tb %TY, %TT"]])
function findLatestModifiedFiles() {
local d="${1:-.}"
local m="${2:-10}"
local f="${3:-%Td %Tb %TY, %TT}"
find "$d" -type f -printf "%T@ :$f %p\n" | sort -nr | cut -d: -f2- | head -n"$m"
}
在目录中找到最新修改的文件:
findLatestModifiedFiles "/home/jason/" 1
您还可以指定自己的日期/时间格式作为第三个参数。
答案 12 :(得分:1)
以下内容将返回时间戳的字符串以及具有最新时间戳的文件名:
find $Directory -type f -printf "%TY-%Tm-%Td-%TH-%TM-%TS %p\n" | sed -r 's/([[:digit:]]{2})\.([[:digit:]]{2,})/\1-\2/' | sort --field-separator='-' -nrk1 -nrk2 -nrk3 -nrk4 -nrk5 -nrk6 -nrk7 | head -n 1
导致表单的输出:
<yy-mm-dd-hh-mm-ss.nanosec> <filename>
答案 13 :(得分:1)
这是一个适用于文件名的版本,其中可能包含空格,换行符,整数字符:
find . -type f -printf "%T@ %p\0" | sort -zk1nr
find ... -printf
打印文件修改(EPOCH值),后跟空格和\0
终止的文件名。sort -zk1nr
读取NUL终止的数据并按数字顺序排序由于问题是用Linux标记的,所以我假设gnu
utils可用。
您可以通过以下方式管道:
xargs -0 printf "%s\n"
打印修改时间和按修改时间排序的文件名(最近的第一个)由换行符终止。
答案 14 :(得分:1)
这实际上应该执行OP所指定的操作:
Bash中的单线:
$ for first_level in `find . -maxdepth 1 -type d`; do find $first_level -printf "%TY-%Tm-%Td %TH:%TM:%TS $first_level\n" | sort -n | tail -n1 ; done
给出如下输出:
2020-09-12 10:50:43.9881728000 .
2020-08-23 14:47:55.3828912000 ./.cache
2018-10-18 10:48:57.5483235000 ./.config
2019-09-20 16:46:38.0803415000 ./.emacs.d
2020-08-23 14:48:19.6171696000 ./.local
2020-08-23 14:24:17.9773605000 ./.nano
这将列出每个第一级目录以及这些文件夹中最新文件的可读时间戳,即使该文件位于子文件夹中,也应按照
的要求进行操作“我需要列出所有这些目录的列表 这样,每个第一级目录都会在日期旁边列出 以及其中最近创建/修改的文件的时间。”
答案 15 :(得分:0)
对于那些面对的人
stat: unrecognized option: format
从Heppo's answer(find $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
选项。
答案 16 :(得分:0)
在 mac 上我用这个
find . -type f -exec stat -f "%m %N" "{}" \; | sort -nr | perl -n -e '@a = split / /;print `ls -l $a[1]`' | vim -
如果你想过滤一些文件,你可以使用带有正则表达式的grep,即
find . -type f -exec stat -f "%m %N" "{}" \; | sort -nr | grep -v -E \.class$ | perl -n -e '@a = split / /;print `ls -l $a[1]`' | vim -
答案 17 :(得分:0)
这就是我正在使用的(非常有效):
function find_last () { find "${1:-.}" -type f -printf '%TY-%Tm-%Td %TH:%TM %P\n' 2>/dev/null | sort | tail -n "${2:-10}" }
优点:
用法:
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
答案 18 :(得分:0)
这可以通过bash中的递归函数来完成
设F显示必须按字典顺序排序yyyy-mm-dd等文件的时间,(os依赖?)
F(){ stat --format %y "$1";} # Linux
F(){ ls -E "$1"|awk '{print$6" "$7}';} # SunOS: maybe this could be done easier
R遍历目录的递归函数
R(){ local f;for f in "$1"/*;do [ -d "$f" ]&&R $f||F "$f";done;}
最后
for f in *;do [ -d "$f" ]&&echo `R "$f"|sort|tail -1`" $f";done
答案 19 :(得分:0)
对于普通ls
输出,请使用此选项。没有参数列表,所以它不会太长:
find . | while read FILE;do ls -d -l "$FILE";done
仅针对日期,时间和名称cut
进行了改进:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5
编辑:注意到当前的最高答案按修改日期排序。这就像第二个例子一样容易,因为修改日期是每行的第一个 - 在一端打一个排序:
find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 | sort
答案 20 :(得分:0)
你可以给printf命令找个试试
%Ak文件的最后访问时间 由k指定的格式, 这是
@' or a directive for the C
strftime' 功能。列出了k的可能值 下面; 其中一些可能根本不可用 系统,到期 系统间“strftime”的差异。