Shell 根据扩展名切分文件名,很多shell脚本都涉及修改文件名的操作。我们可能需要在保留扩展名的同时修改文件名、转换文件格式(保留文件名的同时修改扩展名)或提取部分文件名。
shell所具有的一些内建功能允许我们进行文件名相关的处理。
实战演练
借助%
操作符可以从name.extension这种格式中提取name部分(文件名)。下面的例子从sample.jpg中提取了sample:
file_jpg="sample.jpg"
name={file_jpg%.*}
echo File name is:name
输出结果:
File name is: sample
#
操作符可以提取出扩展名。
提取文件名中的 .jpg并存储到变量file_jpg
中:
extension=${file_jpg#*.}
echo Extension is: jpg
输出结果:
Extension is: jpg
工作原理
在第一个例子中,我们使用了%
操作符从形如name.extension的格式中提取出了文件名。
${VAR%.*} 的含义如下。
- 从
$VAR
中删除位于%
右侧的通配符(在上例中是.*
)所匹配的字符串。通配符从右向左进行匹配。 -
给
VAR
赋值,即VAR=sample.jpg
。通配符从右向左匹配到的内容是.jpg,因此从$VAR
中删除匹配结果,得到输出sample
。
%
属于非贪婪(non-greedy)操作。它从右向左找出匹配通配符的最短结果。还有另一个操作符%%
,它与%
相似,但行为模式却是贪婪的,这意味着它会匹配符合通配符的最长结果。例如,我们现在有这样一个文件:
VAR=hack.fun.book.txt
使用%
操作符从右向左执行非贪婪匹配,得到匹配结果.txt:
$ echo ${VAR%.*}
命令输出:hack.fun.book
。
使用%%
操作符从右向左执行贪婪匹配,得到匹配结果.fun.book.txt
:
$ echo ${VAR%%.*}
命令输出:hack
。
#
操作符可以从文件名中提取扩展名。这个操作符与%
类似,不过求值方向是从左向右。
${VAR#*.}
的含义如下:
从$VARIABLE
中删除位于#
右侧的通配符(即在上例中使用的*.
)从左向右所匹配到的字符串。
和%%
类似,#
也有一个对应的贪婪操作符##
。
##
从左向右进行贪婪匹配,并从指定变量中删除匹配结果。来看一个例子:
VAR=hack.fun.book.txt
使用#
操作符从左向右执行非贪婪匹配,得到匹配结果hack
:
$ echo ${VAR#*.}
命令输出:fun.book.txt
。
使用##
操作符从左向右执行贪婪匹配,得到匹配结果hack.fun.book
:
$ echo ${VAR##*.}
命令输出:txt
。
考虑到文件名中可能包含多个
.
字符,所以相较于#
,##
更适合于从中提取扩展名。##
执行的是贪婪匹配,因而总是能够准确地提取出扩展名。
这里有个能够提取域名中不同部分的实例。假定URL为www.google.com:
$ echo ${URL%.*} # 移除.*所匹配的最右边的内容
www.google
$ echo ${URL%%.*} # 将从右边开始一直匹配到最左边的.*(贪婪操作符)移除
www
$ echo ${URL#*.} # 移除*.所匹配的最左边的内容
google.com
$ echo ${URL##*.} # 将从左边开始一直匹配到最右边的*.(贪婪操作符)移除
com