How to recursively find the latest modified file in a directory?
在执行递归调用时,
1 | ls -altR . | head -n 3 |
如何在目录(包括子目录)中查找最近修改的文件?
1 2 | find . -type f -printf '%T@ %p ' | sort -n | tail -1 | cut -f2- -d"" |
对于一棵大树来说,
编辑:正如
我漏掉了复数的部分,如果你想要更多的文件,只需要增加尾部的参数。
下面是@plundra的答案,下面是BSD和OS X版本:
1 2 | find . -type f -print0 | xargs -0 stat -f"%m %N" | sort -rn | head -1 | cut -f2- -d"" |
您可以使用awk只打印修改时间最长的结果(在UNIX时间),而不是对结果进行排序并只保留最后修改的结果:
1 2 3 4 5 6 7 8 9 | find . -type f -printf"%T@\0%p\0" | awk ' { if ($0>max) { max=$0; getline mostrecent } else getline } END{print mostrecent}' RS='\0' |
如果文件数量足够大,这应该是解决问题的更快方法。
我使用了nul字符(即 ),因为理论上,文件名可以包含任何字符(包括空格和换行符),但是。
如果系统中没有这样的病理文件名,也可以使用换行符:
1 2 3 4 5 6 7 8 9 10 11 12 | find . -type f -printf"%T@ %p " | awk ' { if ($0>max) { max=$0; getline mostrecent } else getline } END{print mostrecent}' RS=' ' |
此外,这也适用于模型。
我很难在Solaris10下找到最后一个修改过的文件。其中
1 | find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6,"",$7 }' | sort | tail -1 |
要显示文件名,请使用
1 | find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6,"",$7,"",$9 }' | sort | tail -1 |
解释
find . -type f 查找并列出所有文件sed 's/.*/"&"/' 用引号括住路径名以处理空白xargs ls -E 将引用的路径发送到ls ,-E 选项确保返回完整的时间戳(格式为年-月-日-时-秒-纳秒)。awk '{ print $6,"",$7 }' 只提取日期和时间awk '{ print $6,"",$7,"",$9 }' 提取日期、时间和文件名sort 返回按日期排序的文件tail -1 只返回上次修改的文件
这似乎工作得很好,即使是在子目录中:
1 | find . -type f | xargs ls -ltr | tail -n 1 |
如果文件太多,请优化查找。
显示具有人类可读时间戳的最新文件:
1 2 | find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p '| sort -n | tail -n1 |
结果如下:
1 | 2015-10-06 11:30: +0200 ./foo/bar.txt |
要显示更多文件,请用更大的数字替换
这将给出一个排序列表:
1 | find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5 |
通过在排序命令中放置"-r"来颠倒顺序。如果只需要文件名,请在"head"之前插入"awk"打印$11""
在Ubuntu13上,下面的操作可能要快一点,因为它颠倒了类型,使用"head"而不是"tail",减少了工作。要在树中显示11个最新文件:
找到。-类型F-printf"%t@%p"sort-n-r head-11 cut-f2-d"s e d-e's,^./,,'xargs l s-u-l
这将给出一个完整的ls列表,而不需要重新排序,并且省略了"find"在每个文件名上放置的恼人的"./"。
或者,作为bash函数:
1 2 3 4 5 6 7 8 9 10 | treecent () { local numl if [[ 0 -eq $# ]] ; then numl=11 # Or whatever default you want. else numl=$1 fi find . -type f -printf '%T@ %p ' | sort -n -r | head -${numl} | cut -f2- -d"" | sed -e 's,^\./,,' | xargs ls -U -l } |
尽管如此,大部分工作还是由普朗德拉的原始解决方案完成的。谢谢你。
我一直在使用类似的东西,以及最近修改过的文件的顶级列表。对于大型目录树,避免排序可能更快。如果只是Top-1最近修改的文件:
1 2 | find . -type f -printf '%T@ %p ' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()' |
在一个包含170万个文件的目录中,我得到了3.4s中最新的一个,比使用sort的25.5s解决方案快7.5x。
我也面临同样的问题。我需要递归地查找最新的文件。查找大约需要50分钟。
下面是一个小脚本,可以更快地完成任务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/sh CURRENT_DIR='.' zob () { FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1) if [ ! -f ${FILE} ]; then CURRENT_DIR="${CURRENT_DIR}/${FILE}" zob fi echo $FILE exit } zob |
它是一个递归函数,用于获取目录的最新修改项。如果该项是一个目录,则递归调用函数并搜索到该目录等。
这个简单的CLI也可以工作:
1 | ls -1t | head -1 |
您可以将-1更改为要列出的文件数
如果在每个文件上单独运行
1 | find . -type f -print0 | xargs -0 stat -f"%m %N" | sort -n | tail -1 | cut -f2- -d"" |
这会将当前目录中所有目录的修改时间递归更改为每个目录中的最新文件:
1 2 | for dir in */; do find $dir -type f -printf '%T@"%p" ' | sort -n | tail -1 | cut -f2- -d"" | xargs -I {} touch -r {} $dir; done |
我发现上面的命令很有用,但是对于我的情况,我需要查看文件的日期和时间,并且我对名称中有空格的几个文件有一个问题。这是我的工作方案。
1 2 | find . -type f -printf '%T@ %p ' | sort -n | tail -1 | cut -f2- -d"" | sed 's/.*/"&"/' | xargs ls -l |
我发现以下内容较短,且具有更多可解释的输出:
1 2 | find . -type f -printf '%TF %TT %p ' | sort | tail -1 |
考虑到标准化的ISO格式日期时间的固定长度,词典编纂排序很好,我们不需要对排序使用
如果要再次删除时间戳,可以使用:
1 2 | find . -type f -printf '%TFT%TT %p ' | sort | tail -1 | cut -f2- -d' ' |
以下命令适用于Solaris:
1 | find . -name"*zip" -type f | xargs ls -ltr | tail -1 |
忽略隐藏的文件-具有良好和快速的时间戳
1 2 | $ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p ' |sort -nr |head -n 10 |
结果
处理好文件名中的空格-不应该使用这些空格!
1 2 3 4 | 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 |
更多
更多的
我为这个问题编写了一个pypi/github包,因为我也需要一个解决方案。
https://github.com/bucknerns/logtail网站
安装:
1 | pip install logtail |
用法:tails changed files
1 | logtail <log dir> [<glob match: default=*.log>] |
用法2:在编辑器中打开最新更改的文件
1 | editlatest <log dir> [<glob match: default=*.log>] |
我喜欢这个,它比较短:
1 | find . -type f -print0|xargs -0 ls -drt|tail -n 1 |