Bash 函数查找与模式匹配的最新文件
- 2024-10-18 09:00:00
- admin 原创
- 71
问题描述:
在 Bash 中,我想创建一个函数,返回与特定模式匹配的最新文件的文件名。例如,我有一个文件目录,如下所示:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
我想要以“b2”开头的最新文件。如何在 bash 中执行此操作?我需要将其包含在~/.bash_profile
脚本中。
解决方案 1:
该ls
命令有一个按时间排序的参数-t
。然后您可以使用 抓取第一个(最新的)head -1
。
ls -t b2* | head -1
但要注意:为什么不应该解析 ls 的输出
我的个人观点:ls
当文件名包含空格或换行符等奇怪字符时,解析是危险的。
如果您可以保证文件名不包含奇怪的字符(可能是因为您可以控制文件的生成方式),那么解析ls
是相当安全的。
如果您正在开发一个脚本,该脚本需要由许多人在许多不同情况下在许多系统上运行,那么请不要解析ls
。
安全操作方法如下:
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
有关更多解释,请阅读如何在目录中找到最新(最新、最早、最旧)的文件?
测试、单方括号和双方括号之间有什么区别?
解决方案 2:
find
和的组合ls
非常适合
文件名不带换行符
文件数量不是很多
文件名不太长
解决方案:
find . -name "my-pattern" -print0 |
xargs -r -0 ls -1 -t |
head -1
让我们分解一下:
我们可以匹配所有有趣的文件,如下find
所示:
find . -name "my-pattern" ...
然后使用-print0
我们可以将所有文件名安全地传递给ls
这样的:
find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t
find
可以在此处添加其他搜索参数和模式
find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t
ls -t
将按修改时间对文件进行排序(最新的在前),并一行打印一个。您可以使用-c
按创建时间排序。注意:这将中断包含换行符的文件名。
最后head -1
得到排序列表中的第一个文件。
注意: xargs
使用系统限制参数列表的大小。如果超出此大小,xargs
将多次调用ls
。这将破坏排序,也可能破坏最终输出。运行
xargs --show-limits
检查你的系统的限制。
注2:find . -maxdepth 1 -name "my-pattern" -print0
如果您不想通过子文件夹搜索文件,请使用。
注 3:正如 @starfry 指出的那样 -如果没有文件与 匹配,-r
的参数xargs
将阻止 的调用。感谢您的建议。ls -1 -t
`find`
解决方案 3:
这是所需 Bash 函数的可能实现:
# Print the newest file, if any, matching the given pattern
# Example usage:
# newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
# Use ${1-} instead of $1 in case 'nounset' is set
local -r glob_pattern=${1-}
if (( $# != 1 )) ; then
echo 'usage: newest_matching_file GLOB_PATTERN' >&2
return 1
fi
# To avoid printing garbage if no files match the pattern, set
# 'nullglob' if necessary
local -i need_to_unset_nullglob=0
if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
shopt -s nullglob
need_to_unset_nullglob=1
fi
newest_file=
for file in $glob_pattern ; do
[[ -z $newest_file || $file -nt $newest_file ]] \n && newest_file=$file
done
# To avoid unexpected behaviour elsewhere, unset nullglob if it was
# set by this function
(( need_to_unset_nullglob )) && shopt -u nullglob
# Use printf instead of echo in case the file name begins with '-'
[[ -n $newest_file ]] && printf '%s
' "$newest_file"
return 0
}
它仅使用 Bash 内置命令,并且可以处理名称包含换行符或其他不寻常字符的文件。
解决方案 4:
使用查找命令。
假设您正在使用 GNU find,您可以将其`-printf '%T+ %p
'`用于文件时间戳值。
find . -type f -printf '%T+ %p
' | sort -r | head -n 1 | cut -d' ' -f2
例子:
find ~/Downloads -type f -printf '%T+ %p
' | sort -r | head -n 1 | cut -d' ' -f2
有关更有用的脚本,请参阅此处的find-latest脚本:https: //github.com/l3x/helpers
解决方案 5:
您可以使用stat
文件 glob 和 decorate-sort-undecorate 并在前面添加文件时间:
$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-
正如评论所述,最好的跨平台解决方案可能是使用 Python、Perl 或 Ruby 脚本。
对于这样的事情,我倾向于使用 Ruby,因为它非常容易编写小型、一次性脚本,同时又具有从命令行执行的 Python 或 Perl 的强大功能。
这是一颗红宝石:
ruby -e '
# index [0] for oldest and [-1] for newest
newest=Dir.glob("*").
reject { |f| File.directory?(f)}.
sort_by { |f| File.birthtime(f) rescue File.mtime(f)
}[-1]
p newest'
这将获取当前工作目录中的最新文件。
**/*
您还可以通过使用in使 glob 递归,或使用等glob
限制匹配的文件b2*
解决方案 6:
Bash 函数用于查找与模式匹配的目录下的最新文件
#1. Make a bash function:
newest_file_matching_pattern(){
find $1 -name "$2" -print0 | xargs -0 ls -1 -t | head -1
}
#2. Setup a scratch testing directory:
mkdir /tmp/files_to_move;
cd /tmp/files_to_move;
touch file1.txt;
touch file2.txt;
touch foobar.txt;
#3. invoke the function:
result=$(newest_file_matching_pattern /tmp/files_to_move "file*")
printf "result: $result
"
印刷:
result: /tmp/files_to_move/file2.txt
或者,如果脆弱的 bash parlor tricks 分包给 python 解释器更符合你的视角,那么这会做同样的事情:
#!/bin/bash
function newest_file_matching_pattern {
python - <<END
import glob, os, re
print(sorted(glob.glob("/tmp/files_to_move/file*"), key=os.path.getmtime)[0]);
END
}
result=$(newest_file_matching_pattern)
printf "result: $result
"
印刷:
result: /tmp/files_to_move/file2.txt
解决方案 7:
不常见的文件名(比如包含有效`
`字符的文件)可能会对这种解析造成严重破坏。以下是在 Perl 中执行此操作的一种方法:
perl -le '@sorted = map {$_->[0]}
sort {$a->[1] <=> $b->[1]}
map {[$_, -M $_]}
@ARGV;
print $sorted[0]
' b2*
那里使用的就是Schwartzian 变换。
解决方案 8:
对于 Google 员工来说:
ls -t | head -1
-t
按上次修改日期时间排序head -1
仅返回第一个结果
(请勿在生产中使用)
解决方案 9:
合并find
、、和。stat
sort
`cut`tail
find
文件-type f
(匹配名称-name 'b2*'
)xargs stat
统计这些文件打印%Y
自纪元以来的秒数和%n
文件名sort
那cut
字段-f
2 及以上2-
(制表符分隔)tail
最后-n 1
一个获取最新文件
适用于所有使用 GNU coreutils 的 shell
tab=$(printf ' ');
find . -type f -print0 |
xargs -0 stat --format "%Y$tab%n" |
sort |
cut -f 2- |
tail -n 1
可以随意用“$tab”替换文字制表符,但它在 SO 上不起作用。
OP 要求过滤以 开头的文件的名称b2
,因此
tab=$(printf ' ');
find . -type f -name 'b2*' -print0 |
xargs -0 stat --format "%Y$tab%n" |
sort |
cut -f 2- |
tail -n 1
解决方案 10:
有一种更有效的方法可以实现这一点。考虑以下命令:
find . -cmin 1 -name "b2*"
此命令使用通配符搜索“b2*”查找一分钟前生成的最新文件。如果您想要过去两天的文件,那么最好使用以下命令:
find . -mtime 2 -name "b2*"
“.”代表当前目录。希望这能有所帮助。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件