Shell 截取文件名和后綴


截取文件名和后綴

編寫Shell腳本的過程中,經常會和文件名和文件路徑打交道。如果用戶輸入了一個文件的全名(可能包含絕對路徑和文件后綴),如何得到文件的路徑名,文件名,文件后綴這些信息呢。Shell腳本擁有強大的字符串處理能力,如果把文件名當做字符串,我們不難使用cut或sed這樣的工具得到我們想要的結果。

1
2
3
4
5
6
7
$fullfile=/the/path/foo.txt
$fullname=$(basename $fullfile)
$dir=$(dirname $fullfile)
$filename=$(echo $fullname | cut -d . -f1)
$extension=$(echo $fullname | cut -d . -f2)
$ echo $dir , $fullname , $filename , $extension
/the/path , foo.txt , foo , txt
 

這里使用basename命令可以直接得到包含后綴的文件名,而dirname命令可以得到路徑名,然后就能簡單的用cut截取文件名和后綴名。

更復雜的情況

如果對付簡單應用場景,到這里已經可以打完收工了,但是有時候文件可能不止有一個后綴,比如*.tar.gz,怎樣得到最后一個后綴呢?再cut一回?當然可以,但是如果文件名是mylib.1.0.1a.zip這樣的呢?呃……正則表達式肯定可以。

1
2
3
4
5
$ fullname=mylib.1.0.1a.zip
$ filename=$(echo $fullname | sed 's/\.[^.]*$//')
$ extension=$(echo $fullname | sed 's/^.*\.//')
$ echo $filename, $extension
mylib.1.0.1a, zip
 

這里面的邏輯是這樣的:

  • 文件名:把以.字符開頭以后一直到行尾都是非.字符的子串替換為空。
  • 后綴名:把從行首開始以.字符結尾的子串替換為空。

光用語言把這兩個正則表達式描述出來腦細胞也要死不少。有沒有像上面cut版本一樣簡單容易理解的方法呢?由於.分隔符的個數不確定,正常使用cut來分割最后一個.字符是不太可能的。但是我們可使用 rev 命令將字符串反轉一下,區分后綴和文件名的.字符位置就確定了。截取了想要的部分之后,再次反轉就得到了我們想要的內容。

1
2
3
4
5
$ fullname=mylib.1.0.1a.zip
$ filename=$(rev <<< $fullname | cut -d . -f2- | rev)
$ extension=$(rev <<< $fullname | cut -d . -f1 | rev)
$ echo $filename, $extension
mylib.1.0.1a, zip
 

使用參數擴展

其實不借助復雜的正則表達式,甚至不調用basename, dirname, cut, sed命令,shell腳本一樣可以做到所有的操作。看下面的實現:

1
2
3
4
5
6
7
$ fullfile=/the/path/mylib.1.0.1a.zip
$ fullname="${fullfile##*/}"
$ dir="${fullfile%/*}"
$ extension="${fullname##*.}"
$ filename="${fullname%.*}"
$ echo $dir , $fullname , $filename , $extension
/the/path , mylib.1.0.1a.zip , mylib.1.0.1a , zip
 

真是不能再簡潔了,大括號之內變量名配合幾個神奇的字符,就是Shell的參數擴展(Parameter Extension)功能。

  • ${fullfile##*/}:從前面開始刪除fullfile中最大匹配(longest matching pattern) */ 的字符串
  • ${fullfile%/*}:從后面開始刪除fullfile中最小匹配(shortest matching pattern) /* 的字符串
  • ${fullname##*.}:從前面開始刪除fullname中最大匹配(longest matching pattern) *. 的字符串
  • ${fullname%.*}:從后面開始刪除fullname中最小匹配(shortest matching pattern) .* 的字符串

參數擴展有多種形式,在shell編程中可以用作參數的拼接,字符串的替換,參數列表截取,變量初值等操作,這里不再詳述,請參考后面的功能列表和官方文檔

參數擴展功能列表

參數形式 擴展后
x{y,z} xy xz
${x}{y, z} ${x}y ${x}z
${x}{y, $z} ${x}y ${x}${z}
${param#pattern} 從param前面刪除pattern的最小匹配
${param##pattern} 從param前面刪除pattern的最大匹配
${param%pattern} 從param后面刪除pattern的最小匹配
${param%%pattern} 從param后面刪除pattern的最大匹配
${param/pattern/string} 從param中用string替換pattern的第一次匹配,string可為空
${param//pattern/string} 從param中用string替換pattern的所有匹配,string可為空
${param:3:2} 截取$param中索引3開始的2個字符
${param:3} 截取$param中索引3至末尾的字符
${@:3:2} 截取參數列表$@中第3個開始的2個參數
${param:-word} 若$param為空或未設置,則參數式返回word,$param不變
${param:+word} 若$param為非空,則參數式返回word,$param不變
${param:=word} 若$param為空或為設置,則參數式返回word,同時$param設置為word
${param:?message} 若$param為空或為設置,則輸出錯誤信息message,若包含空白符,則需引號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM