shell中切分文件名和扩展名

对于shell涉及的修改文件名的操作,我们可能需要提取某个文件名,或者提取某个文件的扩展名。get✔

根据扩展名切分文件名

截取文件名称示例:

1
2
3
4
5
$ cat file.sh 

file_jpg="sample.jpg"
name=${file_jpg%.*}
echo File name is:$name

输出结果如下:

1
2
$ ./file.sh 
File name is:sample

截取文件扩展名示例:

1
2
3
4
5
$ cat file1.sh
#!/bin/sh
file_jpg="sample.jpg"
extension=${file_jpg#*.}
echo Extension is:$extension

输出结果如下:

1
2
$ ./file1.sh
Extension is:jpg

${VAR%.*}工作原理:

  • $VAR中删除位于%右侧的通配符(在上例中式.*),通配符从右向左进行匹配。
  • VAR赋值,即VAR=sample.jpg,通配符从右向左匹配得到的内容是.jpg,因此从$VAR中删除匹配结果,得到输出结果sample。

💡 那么,有没有考虑过,要是文件名有很多后缀呢cute.a.b.c.d.txt?要是提取的变量为域名www.google.com呢?有的是办法,往下看~

%属于非贪婪匹配,它从右向左找出匹配通配符的最短结果。还有另一个操作符%%,它于%相似,但行为模式确是贪婪的,它会匹配符合通配符的最长结果。

1
2
3
4
5
6
7
8

$ var=hack.fun.book.txt
# 执行从右向左非贪婪匹配,得到的匹配结果为.txt,删除了.txt之后文件名,可以得到具体的文件名
$ echo ${var%.*}
hack.fun.book
# 执行从右向左贪婪匹配,得到结果.fun.book.txt,删除了.fun.book.txt
$ echo ${var%%.*}
hack

${VAR#*.}工作原理:

  • $VAR中删除位于#右侧的通配符(上个栗子中使用的*.),从左到右匹配字符串。
  • #对应的贪婪操作是##
1
2
3
4
5
6
# 从右到左进行非贪婪匹配,得到匹配结果hack,从指定变量中删除匹配结果
$ echo ${var#*.}
fun.book.txt
# 从右到左进行非贪婪匹配,得到匹配结果hack.fun.book,删除匹配结果后得到扩展名
$ echo ${var##*.}
txt

💡总结

文件名中可能包含多个.字符,所以呢

对于文件名:相较于%%,%更适合于提取文件名。%执行的是非贪婪匹配,只会删除扩展名。

对于扩展名:相较于#,##更适合于从中提取扩展名。##执行的是贪婪匹配,因此能准确的提取扩展名。