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

Bash 如何在目录中递归查找最新修改的文件?,bash,filesystems,find,Bash,Filesystems,Find,执行递归调用时,ls似乎无法正确排序文件: ls -altR . | head -n 3 如何在目录(包括子目录)中找到最近修改的文件 对于一棵巨树,sort可能很难将所有内容都保存在内存中 %T@像unix时间戳一样为您提供修改时间,sort-n按数字排序,tail-1获取最后一行(最高时间戳),cut-f2-d”“从输出中删除第一个字段(时间戳) Edit:正如-printf可能只是GNU一样,ajreals对stat-c的使用也是如此。虽然可以在BSD上执行相同的操作,但格式化的选项是不

执行递归调用时,
ls
似乎无法正确排序文件:

ls -altR . | head -n 3
如何在目录(包括子目录)中找到最近修改的文件


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

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

Edit:正如
-printf
可能只是GNU一样,ajreals对
stat-c
的使用也是如此。虽然可以在BSD上执行相同的操作,但格式化的选项是不同的(
-f“%m%N”


我错过了复数的部分;如果您想要比最新文件更多的内容,只需增加tail参数。

这将提供一个排序列表:

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

通过在sort命令中放置'-r'来颠倒顺序。如果您只需要文件名,请在“|head”之前插入“awk”{print$11}'|“

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

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

我使用了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。

接下来是BSD和OS X版本:

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

如果对每个文件单独运行
stat
会降低速度,则可以使用
xargs
将速度提高一点:

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

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

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

我很难在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
解释

  • find-键入f
    查找并列出所有文件
  • sed的/*/“&”/
    将路径名用引号括起来以处理空白
  • xargs ls-E
    将引用的路径发送到
    ls
    -E
    选项确保返回完整的时间戳(格式为年-月-日-时-分-秒-纳秒)
  • awk'{print$6,“,$7}'
    只提取日期和时间
  • awk'{print$6,“,$7,”,$9}'
    提取日期、时间和文件名
  • sort
    返回按日期排序的文件
  • tail-1
    仅返回上次修改的文件

    • 在Ubuntu13上,下面的操作可能会稍微快一点,因为它会反转排序并使用“head”而不是“tail”,从而减少了工作量。要在树中显示11个最新文件,请执行以下操作:

      查找-类型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。

      这似乎可以很好地工作,即使使用子目录:

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

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

      我发现上面的命令很有用,但对于我的情况,我还需要查看文件的日期和时间,因为有几个文件的名称中有空格。 这是我的工作方案

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

      我更喜欢这个,它比较短:

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

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

      ls -1t | head -1
      

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

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

      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
      替换为一个更高的数字

      我遇到了同样的问题。我需要递归地查找最近的文件。find花了大约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
      

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

      以下命令在Solaris上运行:

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

      我一直在使用类似的东西,以及最近修改过的文件的top-k列表。对于大型目录树,它可以更快地避免排序。对于仅为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倍。

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

      安装:

      pip install logtail
      
      用法:更改文件

      logtail <log dir> [<glob match: default=*.log>]
      
      logtail[]
      
      用法2:在编辑器中打开最新更改的文件

      editlatest <log dir> [<glob match: default=*.log>]
      
      editlatest[]
      
      忽略隐藏的文件-具有漂亮快速的时间戳 下面是如何在包含子目录的目录中查找并列出最新修改的文件。故意忽略隐藏的文件。时间格式可以定制

      $ 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
      
      更多
      find
      galore在链接后面。

      我发现以下内容更短,输出更具解释性:

      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' '
      

      要搜索/target_目录及其所有子目录中已删除的文件,请执行以下操作:
      find . -type f -printf '%TF %TT %p\n' | sort | tail -1
      
      find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '
      
      $ find /target_directory -type f -mmin -60
      
      $ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
      
      #!/bin/sh
      # Finds most recently modified files.
      rsync -rL --list-only "$@" | grep -v '^d' | sort -k3,4r | head -5
      
      backup  /var/atlassian/application-data/jira/current/   home    +rsync_long_args=--archive --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"
      
      - log/
      - logs/
      - analytics-logs/
      - tmp/
      - monitor/*.rrd4j
      
      findlatest /var/atlassian/application-data/jira/current/ --filter="merge /opt/atlassian/jira/current/backups/rsync-excludes"