Bash函数来查找最新的文件匹配模式
在Bash中,我想创build一个函数,返回匹配特定模式的最新文件的文件名。 例如,我有一个像这样的文件的目录:
Directory/ a1.1_5_1 a1.2_1_4 b2.1_0 b2.2_3_4 b2.3_2_0
我想要以“b2”开头的最新文件。 我如何在bash中做到这一点? 我需要在我的~/.bash_profile
脚本中有这个。
ls
命令有一个参数-t
按时间sorting。 然后你可以抓住head -1
(最新)。
ls -t b2* | head -1
但要小心: 为什么你不应该分析ls的输出
我的个人意见:parsingls
只有当文件名可以包含空格或换行符等有趣的字符时才是危险的。 如果你可以保证文件名不包含有趣的字符,那么parsingls
是相当安全的。
如果你正在开发一个脚本,在许多不同的情况下,许多系统上运行的脚本,我非常推荐不要分析ls
。
这里是如何做到“正确”: 我怎样才能find目录中的最新(最新,最早,最旧)文件?
unset -v latest for file in "$dir"/*; do [[ $file -nt $latest ]] && latest=$file done
这是所需的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 ]] \ && 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\n' "$newest_file" return 0 }
它只使用Bash内build函数,并且应该处理名称中包含换行符或其他不常用字符的文件。
不寻常的文件名(例如包含有效的\n
字符的文件可能会对这种parsing产生巨大的影响,下面是在Perl中执行的一种方法:
perl -le '@sorted = map {$_->[0]} sort {$a->[1] <=> $b->[1]} map {[$_, -M $_]} @ARGV; print $sorted[0] ' b2*
那是在那里使用的Schwartzian变换 。
有一个更有效的方法来实现这一点。 考虑下面的命令:
find . -cmin 1 -name "b2*"
这个命令find刚刚一分钟前产生的最新文件,在“b2 *”上进行通配符search。 如果你想从最近两天的文件,那么你最好使用下面的命令:
find . -mtime 2 -name "b2*"
“。” 代表当前目录。 希望这可以帮助。