首页 文章

如何递归查找目录中的最新修改文件?

提问于
浏览
209

看起来 ls 在进行递归调用时没有正确排序文件:

ls -altR . | head -n 3

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

19 回答

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

    对于一棵巨大的树, sort 可能很难将所有内容保存在内存中 .

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

    Edit: 就像 -printf 可能只是GNU一样,ajreals的使用也是 stat -c . 虽然可以在BSD上执行相同的操作,但格式化的选项是不同的( -f "%m %N" 看起来似乎)

    我错过了复数的部分;如果你想要更多的最新文件,只需提高尾部参数 .

  • 10

    关注@plundra's answer,这是BSD和OS X版本:

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

    您可以使用awk仅打印具有最大修改时间(在unix时间内)的结果,而不是对结果进行排序并仅保留最后修改的结果:

    find . -type f -printf "%T@\0%p\0" | awk '
        {
            if ($0>max) {
                max=$0; 
                getline mostrecent
            } else 
                getline
        } 
        END{print mostrecent}' RS='\0'
    

    如果文件数量足够大,这应该是解决问题的更快方法 .

    我使用了NUL字符(即'\ 0'),因为理论上,文件名可能包含任何字符(包括空格和换行符)但是 .

    如果您的系统中没有这样的病态文件名,您也可以使用换行符:

    find . -type f -printf "%T@\n%p\n" | awk '
        {
            if ($0>max) {
                max=$0; 
                getline mostrecent
            } else 
                getline
        } 
        END{print mostrecent}' RS='\n'
    

    另外,这也适用于mawk .

  • 3

    我在Solaris 10下找到最后修改的文件时遇到了麻烦 . 有 find 没有 printf 选项且 stat 不可用 . 我发现以下解决方案对我有用:

    find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1
    

    要显示文件名以及使用

    find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1
    

    Explanation

    • find . -type f 查找并列出所有文件

    • sed 's/.*/"&"/' 将路径名包装在引号中以处理空格

    • xargs ls -E 将引用的路径发送到 ls-E 选项确保返回完整时间戳(格式年 - 月 - 日小时 - 分 - 秒 - 纳秒)

    • awk '{ print $6," ",$7 }' 仅提取日期和时间

    • awk '{ print $6," ",$7," ",$9 }' 提取日期,时间和文件名

    • sort 返回按日期排序的文件

    • tail -1 仅返回上次修改的文件

  • 2

    这似乎工作正常,即使对于子目录:

    find . -type f | xargs ls -ltr | tail -n 1
    

    如果文件太多,请优化查找 .

  • 312

    显示具有人类可读时间戳的最新文件:

    find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
    

    结果如下所示:

    2015-10-06 11:30: +0200 ./foo/bar.txt
    

    要显示更多文件,请将 -n1 替换为更高的数字

  • 1

    这给出了一个排序列表:

    find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5
    

    通过在sort命令中放置'-r'来反转顺序 . 如果您只想要文件名,请插入“awk'{print $ 11}'|”之前'|头'

  • 0

    在Ubuntu 13上,以下内容可能会更快,因为它可以反转排序并使用“head”而不是“tail”,从而减少了工作量 . 要显示树中的11个最新文件:

    find . -type f -printf '%T@ %p\n' | sort -n -r | head -11 | cut -f2- -d" " | sed -e 's,^./,,' | xargs ls -U -l

    这给出了一个完整的ls列表,没有重新排序,省略了烦人的'./','find'放在每个文件名上 .

    或者,作为bash函数:

    treecent () {
      local numl
      if [[ 0 -eq $# ]] ; then
        numl=11   # Or whatever default you want.
      else
        numl=$1
      fi
      find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} |  cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
    }
    

    尽管如此,大多数工作都是由plundra的原始解决方案完成的 . 谢谢plundra .

  • 2

    如果单独在每个文件上运行 stat 会变慢,则可以使用 xargs 来加快速度:

    find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
    
  • 9

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

    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
    
  • 0

    这个简单的cli也可以工作:

    ls -1t | head -1
    

    您可以将-1更改为要列出的文件数

  • 0

    我遇到了同样的问题 . 我需要递归地找到最新的文件 . 发现花了大约50分钟才找到 .

    这是一个快速完成它的小脚本:

    #!/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
    

    它是一个递归函数,可以获取目录中最新修改的项目 . 如果此项目是目录,则递归调用该函数并搜索此目录等 .

  • 4

    我一直使用类似的东西,以及最近修改过的文件的top-k列表 . 对于大型目录树,它可以是 much faster to avoid sorting . 对于最近修改过的top-1文件:

    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.4s中的最新文件,与使用sort的25.5s解决方案相比,速度提高了7.5倍 .

  • 2

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

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

    以下命令适用于Solaris:

    find . -name "*zip" -type f | xargs ls -ltr | tail -1
    
  • 2

    我更喜欢这个,它更短:

    find . -type f -print0|xargs -0 ls -drt|tail -n 1
    
  • 0

    我为这个问题写了一个pypi / github包,因为我也需要一个解决方案 .

    https://github.com/bucknerns/logtail

    安装:

    pip install logtail
    

    用法:tails更改文件

    logtail <log dir> [<glob match: default=*.log>]
    

    用法2:在编辑器中打开最新更改的文件

    editlatest <log dir> [<glob match: default=*.log>]
    
  • 6

    忽略隐藏文件 - 具有漂亮和快速的时间戳

    处理文件名中的空格 - 不是你应该使用它们!

    $ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |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
    

    可以通过以下链接找到More find galore .

  • 2

    我发现以下更短并且具有更多可解释的输出:

    find . -type f -printf '%TF %TT %p\n' | sort | tail -1
    

    鉴于标准ISO格式日期时间的固定长度,字典排序很好,我们不需要排序上的 -n 选项 .

    如果要再次删除时间戳,可以使用:

    find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
    

相关问题