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
How to recursively find the latest modified file in a directory?
提问by JMW
It seems that ls
doesn'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 sort
to keep everything in memory.
对于一棵巨大的树,可能很难sort
将所有内容都保存在内存中。
%T@
gives you the modification time like a unix timestamp, sort -n
sorts numerically, tail -1
takes 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 -printf
is probably GNU-only, ajreals usage of stat -c
is 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'
%pfind . -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 find
does not have the printf
option and stat
is 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 f
finds and lists all filessed 's/.*/"&"/'
wraps the pathname in quotes to handle whitespacesxargs ls -E
sends the quoted path tols
, the-E
option makes sure that a full timestamp (format year-month-day hour-minute-seconds-nanoseconds) is returnedawk '{ print $6," ",$7 }'
extracts only date and timeawk '{ print $6," ",$7," ",$9 }'
extracts date, time and filenamesort
returns the files sorted by datetail -1
returns 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 -n1
with 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.
这是一个递归函数,它获取目录的最新修改项。如果此项是目录,则递归调用该函数并搜索该目录等。