首页 文章

如何递归查找并列出具有子目录和时间的目录中的最新修改文件?

提问于
浏览
335
  • 操作系统:Linux

  • 文件系统类型:ext3

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

我有几个目录,其中包含几个子目录和文件 . 我需要列出所有这些目录,这些目录的构造方式使得每个第一级目录都列在其中最新创建/修改的文件的日期和时间旁边 .

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

./alfa/beta/gamma/example.txt

并且我修改了文件 example.txt 的内容,我需要以人类可读的形式显示在第一级目录 alfa 旁边的时间,而不是epoch . 我尝试了一些使用find, xargssort 之类的东西,但是当我创建/修改几个级别的文件时,我可以改变它 .

16 回答

  • 35

    对于普通 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
    
  • 9

    以下内容返回时间戳的字符串以及具有最新时间戳的文件的名称:

    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>

  • 5

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

    find -cmin -N

    例如:

    find -cmin -5

  • 1

    试试这个

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

    它使用 find 从目录中收集所有文件, ls 列出按修改日期排序的文件, head 用于选择第一个文件,最后 stat 用于以良好的格式显示时间 .

    此时,对于名称中带有空格或其他特殊字符的文件,这是不安全的 . 如果它还不能满足您的需求,请写一个表扬 .

  • 0

    快速bash功能:

    # 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
    

    您还可以指定自己的日期/时间格式作为第三个参数 .

  • 155

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

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

    试试这个:

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

    您可以给printf命令找一试

    %Ak文件的最后访问时间采用k指定的格式,即@'或C strftime'函数的指令 . k的可能值列在下面;由于系统之间的“strftime”不同,其中一些可能并非在所有系统上都可用 .

  • 3

    这也可以通过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
    
  • 3

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

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

    $ 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
    

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

  • 1

    我缩短了光环对这个单线的很棒的答案

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

    我在我的.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,所以你可能不需要那个部分 .

  • 0

    此命令适用于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
    
  • 1

    我正在显示最新的访问时间,你可以轻松地修改它来做最新的mod时间 .

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


    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
    

    你有它......

  • 0

    这是一个适用于文件名的版本,它可能包含空格,换行符,glob字符:

    find . -type f -printf "%T@ %p\0" | sort -zk1nr
    
    • find ... -printf 打印文件修改(EPOCH值),后跟空格和 \0 终止的文件名 .

    • sort -zk1nr 读取NUL终止的数据并按数字顺序对其进行排序

    由于问题是用Linux标记的,所以我假设有 gnu utils可用 .

    您可以通过以下方式管道:

    xargs -0 printf "%s\n"
    

    打印由换行符终止的修改时间(最近的第一个)排序的修改时间和文件名 .

  • 33

    这篇文章中的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
        }'
    

    蟒蛇:

    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'
    

相关问题