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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4561895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:00:54  来源:igfitidea点击:

How to recursively find the latest modified file in a directory?

bashfilesystemsfind

提问by JMW

It seems that lsdoesn't sort the files correctly when doing a recursive call:

ls在进行递归调用时,似乎没有正确对文件进行排序:

ls -altR . | head -n 3

How can I find the most recently modified file in a directory (including subdirectories)?

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

回答by plundra

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

For a huge tree, it might be hard for sortto keep everything in memory.

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

%T@gives you the modification time like a unix timestamp, sort -nsorts numerically, tail -1takes the last line (highest timestamp), cut -f2 -d" "cuts away the first field (the timestamp) from the output.

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

Edit:Just as -printfis probably GNU-only, ajreals usage of stat -cis too. Although it is possible to do the same on BSD, the options for formatting is different (-f "%m %N"it would seem)

编辑:就像-printf可能是仅 GNU 一样,ajreals 的使用stat -c也是如此。虽然可以在 BSD 上做同样的事情,但格式化的选项是不同的(-f "%m %N"看起来)

And I missed the part of plural; if you want more then thelatest file, just bump up the tail argument.

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

回答by Emerson Farrugia

Following up on @plundra's answer, here's the BSD and OS X version:

跟进@plundra 的回答,这里是 BSD 和 OS X 版本:

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

回答by marco

Instead of sorting the results and keeping only the last modified ones, you could use awk to print only the one with greatest modification time (in unix time):

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

find . -type f -printf "%T@
find . -type f -printf "%T@\n%p\n" | awk '
    {
        if (
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print ," ", }' | sort | tail -1
>max) { max=
find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print ," ",," ", }' | sort | tail -1
; getline mostrecent } else getline } END{print mostrecent}' RS='\n'
%p
find . -type f | xargs ls -ltr | tail -n 1
" | awk ' { if (
find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1
>max) { max=
2015-10-06 11:30: +0200 ./foo/bar.txt
; getline mostrecent } else getline } END{print mostrecent}' RS='
find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'
'

This should be a faster way to solve your problem if the number of files is big enough.

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

I have used the NUL character (i.e. '\0') because, theoretically, a filename may contain any character (including space and newline) but that.

我使用了 NUL 字符(即 '\0'),因为理论上,文件名可以包含除此之外的任何字符(包括空格和换行符)。

If you don't have such pathological filenames in your system you can use the newline character as well:

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

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

In addition, this works in mawk too.

此外,这也适用于 mawk。

回答by Florian Feldhaus

I had the trouble to find the last modified file under Solaris 10. There finddoes not have the printfoption and statis not available. I discovered the following solution which works well for me:

我在 Solaris 10 下找不到最后修改的文件。那里find没有printf选项,stat也不可用。我发现以下解决方案对我很有效:

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

To show the filename as well use

要显示文件名以及使用

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

Explanation

解释

  • find . -type ffinds and lists all files
  • sed 's/.*/"&"/'wraps the pathname in quotes to handle whitespaces
  • xargs ls -Esends the quoted path to ls, the -Eoption makes sure that a full timestamp (format year-month-day hour-minute-seconds-nanoseconds) is returned
  • awk '{ print $6," ",$7 }'extracts only date and time
  • awk '{ print $6," ",$7," ",$9 }'extracts date, time and filename
  • sortreturns the files sorted by date
  • tail -1returns only the last modified file
  • find . -type f查找并列出所有文件
  • sed 's/.*/"&"/'将路径名用引号括起来以处理空格
  • xargs ls -E将引用的路径发送到ls,该-E选项确保返回完整的时间戳(格式年-月-日时-分-秒-纳秒
  • awk '{ print $6," ",$7 }'仅提取日期和时间
  • awk '{ print $6," ",$7," ",$9 }'提取日期、时间和文件名
  • sort返回按日期排序的文件
  • tail -1只返回最后修改的文件

回答by mgratia

This seems to work fine, even with subdirectories:

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

##代码##

In case of too many files, refine the find.

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

回答by Fabian Schmengler

Shows the latest file with human readable timestamp:

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

##代码##

Result looks like this:

结果如下所示:

##代码##

To show more files, replace -n1with a higher number

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

回答by Pierre D

I use something similar all the time, as well as the top-k list of most recently modified files. For large directory trees, it can be much faster to avoid sorting. In the case of just top-1 most recently modified file:

我一直使用类似的东西,以及最近修改过的文件的前 k 列表。对于大型目录树,避免排序快得多。在只有 top-1 最近修改的文件的情况下:

##代码##

On a directory containing 1.7 million files, I get the most recent one in 3.4s, a speed-up of 7.5x against the 25.5s solution using sort.

在包含 170 万个文件的目录中,我在 3.4 秒内获得了最新的一个,与使用排序的 25.5 秒解决方案相比,速度提高了 7.5 倍。

回答by Karlo

This gives a sorted list:

这给出了一个排序列表:

##代码##

Reverse the order by placing a '-r' in the sort command. If you only want filenames, insert "awk '{print $11}' |" before '| head'

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

回答by RickyS

On Ubuntu 13, the following does it, maybe a tad faster, as it reverses the sort and uses 'head' instead of 'tail', reducing the work. To show the 11 newest files in a tree:

在 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

找 。-type f -printf '%T@ %p\n' | 排序 -n -r | 头-11 | cut -f2- -d" " | sed -e 's,^./,,' | xargs ls -U -l

This gives a complete ls listing without re-sorting and omits the annoying './' that 'find' puts on every file name.

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

Or, as a bash function:

或者,作为 bash 函数:

##代码##

Still, most of the work was done by plundra's original solution. Thanks plundra.

尽管如此,大部分工作还是由 plundra 的原始解决方案完成的。谢谢普伦德拉。

回答by AnatomicJC

I faced the same issue. I need to find the most recent file recursively. find took around 50 minutes to find.

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

Here is a little script to do it faster:

这是一个小脚本,可以更快地完成它:

##代码##

It's a recursive function who get the most recent modified item of a directory. If this item is a directory, the function is called recursively and search into this directory, etc.

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