在bash中获取变量中的最后一个文件名?

Vin*_*ent 5 bash ls

在一个目录中,我有以下文件:

myfile_v01.txt
myfile_v02.txt
myfile_v03.txt
Run Code Online (Sandbox Code Playgroud)

如何制作一个 bash 脚本来检测最后一个版本的值并将最后一个版本的文件名放入一个变量中?

Era*_*iel 14

不是很精致,但看起来很实用:

var=$(ls | sort -V | tail -n 1)
Run Code Online (Sandbox Code Playgroud)

然后你将最后一个文件存储在 $var

  • 仅供参考:为什么你不应该解析 ls(1) 的输出:http://mywiki.wooledge.org/ParsingLs (2认同)

ter*_*don 5

有两种明显的方法,您可以解析文件名或查找最新文件:

  1. 解析文件名,这假设所有文件都按照您的示例命名:

    $ latest=myfile_v$(
        for f in myfile_v*; do 
          ver=${f##myfile_v}; ver=${ver%.txt}; echo $ver; 
        done | sort -n | tail -n 1).txt
    
    Run Code Online (Sandbox Code Playgroud)
  2. 获取最新的文件(假设不包含换行符的相对合理的文件名)

    $ latest=$(ls -tr | tail -n 1)
    
    Run Code Online (Sandbox Code Playgroud)


mpy*_*mpy 5

这是一个使用 globbing 的解决方案(因此不依赖于解析 ls),就像 terdon 的第一个解决方案一样,但不需要迭代所有文件:

myfiles=(myfile_v*)
lastfile="${myfiles[${#myfiles[@]}-1]}"
unset myfiles
Run Code Online (Sandbox Code Playgroud)

首先,所有匹配的文件被读入一个数组。然后,数组的最后一个元素被分配给$lastfile。最后,不再需要该数组,因此可以将其删除。

不幸的是,bash(至少据我所知)不支持对通配符#的结果进行排序,因此此示例适用于您给定的命名方案(恰好两位数,也适用于版本 < 10),但对于myfile_v1.txt, myfile_v2.txt, .. 会失败。 ., myfile_v10.txt.


# zsh(当然;))确实如此,所以zsh% myfiles=(myfile_v*(n)); lastfile="${myfiles[-1]}"; unset myfiles不会受到这个限制。