如何recursion查找和列出目录中的最新修改的文​​件与子目录和时间?

  • 操作系统:Linux

  • 文件系统types:ext3

  • 首选解决scheme:bash(script / oneliner),ruby,python

我有几个目录中有几个子目录和文件。 我需要列出所有以这样一种方式构build的目录,即每个第一级目录在最新创build/修改的文件的date和时间旁边列出。

为了澄清,如果我触摸一个文件或修改其内容的几个子目录级别下,该时间戳应显示在第一级目录名旁边。 说我有一个这样的目录结构:

./alfa/beta/gamma/example.txt 

我修改了example.txt文件的内容,我需要在第一级目录alfa旁边以可读forms显示时间,而不是时间。 我已经尝试了一些使用find, xargssortsort东西,但我无法解决的问题,“阿尔法”的文件系统时间戳不会改变,当我创build/修改文件几个级别。

试试这个:

 #!/bin/bash find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head 

通过它应该开始recursion扫描的目录的path执行它(它支持带空格的文件名)。

如果有很多文件,可能需要一段时间才能返回任何内容。 如果我们使用xargs性能可以得到改善:

 #!/bin/bash find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head 

这是更快一点。

查找文件状态上次更改的所有文件N分钟前:

find -cmin -N

例如:

find -cmin -5

我缩短了光环对这一行的真棒答案

 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"; 

GNU Find(参见man find )有一个-printf参数用于显示文件EPOC mtime和相对path名。

 redhat> find . -type f -printf '%T@ %P\n' | sort -n | awk '{print $2}' 

尝试这个

 #!/bin/bash stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1) 

它使用find来收集目录中的所有文件, ls按修改datesorting, headselect第一个文件,最后stat以一个很好的格式显示时间。

目前,对于名称中带有空格或其他特殊字符的文件是不安全的。 如果它不符合您的需要,写一个推荐。

此命令适用于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的杰出解决scheme,从评论推广到完整答案。 我混合CharlesB的见解,在Mac OS X上使用gstatgstat ,我从MacPorts获得了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 

本文中的perl和Python解决scheme帮助我解决了Mac OS X上的这个问题: https : //unix.stackexchange.com/questions/9247/how-to-list-files-sorted-by-modification-date-recursively -no-stat-command-avail 。

从post引用:

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' 

我在我的.profile中有这个别名,我经常使用它

 $ alias | grep xlogs xlogs='sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R' 

所以它会做你正在寻找的东西(除非它不遍历更改date/时间多个层次) – 寻找最新的文件(在这种情况下* .log和* .trc文件); 也只能find在前一天修改的文件,然后按时间sorting,并通过较less的pipe道输出:

 sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R 

PS。 注意我在某些服务器上没有root权限,但总是有sudo,所以你可能不需要这个部分。

我显示最新的访问时间,你可以很容易地修改这个做最新的MOD时间。

有两种方法可以做到这一点:


1)如果你想避免全局sorting,如果你有数以千万计的文件,那么你可以这样做:(把你自己放在你想要search的目录的根目录下)

 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 

上面的方法打印文件名越来越新的访问时间,最后打印的文件是最近访问时间的文件。 您显然可以使用“尾巴-1”获得最新的访问时间。


2)你可以recursion地查找你的子目录中的所有文件的名称和访问时间,然后根据访问时间和尾部最大的条目进行sorting:

 linux> \find . -type f -exec stat --printf="%X %n\n" {} \; | \sort -n | tail -1 

在那里,你有它…

快速打击function:

 # 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 

您也可以指定自己的date/时间格式作为第三个参数。

以下内容将返回一个包含最新时间戳记的时间戳记和文件名称的string:

 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>

这里有一个与可能包含空格,换行符,水平字符的文件名一起工作的版本:

 find . -type f -printf "%T@ %p\0" | sort -zk1nr 
  • find ... -printf打印文件修改(EPOCH值),后跟一个空格和\0终止的文件名。
  • sort -zk1nr读取NUL终止的数据并对其进行逆向sorting

由于问题被标记为Linux,所以我假设gnu utils可用。

你可以用上面的方法pipe道:

 xargs -0 printf "%s\n" 

打印按修订时间(最近的第一个)按换行符终止的修改时间和文件名。

忽略隐藏的文件 – 带有快捷的时间戳

处理文件名中的空格 – 不是你应该使用这些!

 $ 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 

更多find嘉豪可以通过下面的链接find。

你可以给printf命令试试看

%Ak文件上次访问时间的格式为k,可以是@' or a directive for the C strftime函数@' or a directive for the C 。 下面列出了k的可能值。 由于系统之间的“strftime”不同,有些系统可能不适用于所有系统。

对于普通的ls输出,使用这个。 没有参数列表,所以不能太长:

 find . | while read FILE;do ls -d -l "$FILE";done 

cut好的date,时间和名称的好处:

 find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 

编辑 :只是注意到,当前最热门的答案按修改datesorting。 这和第二个例子一样简单,因为修改date在每一行都是第一个字符 – 在结尾处进行sorting:

 find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 | sort 

这可以用bash中的recursion函数来完成

设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通过目录运行的recursion函数

 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