HOWTO · Bash
使用 Bash 刪除副檔名
在 Bash 中移除檔名的最後一個副檔名、使用 basename 移除已知後綴,或使用 cut 擷取分隔文字欄位。
本頁內容
在 Bash 中移除檔名字串最後的副檔名,可使用參數展開:name="${file%.*}"。%.* 樣式會從字串尾端移除最短的「句點加上任意字元」匹配內容,因此前面的句點會保留下來。這只會變更字串,不會重新命名磁碟上的檔案。
執行下方範例。保留的範例區塊與英文原文完全相同,其中顯示的標籤仍為英文。
file='annual.report.html'
name="${file%.*}"
printf '%s\n' "$name"
使用 Bash 參數展開移除副檔名
如果檔名已存放在 Bash 變數中,參數展開通常是最簡單的選擇,不需要外部命令或管線。將結果指定給新變數可保留原始值;若不再需要原值,也可以直接指定回同一個變數。請為變數展開加上引號,讓空格和萬用字元仍視為檔名字串的一部分。
這個樣式會移除最後一個句點及其後的所有內容。例如,套用於 annual.report.html 會得到 annual.report;套用於沒有句點可匹配的 notes 則會原樣保留。使用此樣式時,像 .profile 這種以句點開頭的名稱會變成空字串;如果資料中包含這類隱藏檔名,請另外處理。這套規則只依文字內容判斷,不會確認副檔名是否代表有意義的檔案類型。
已知副檔名時使用 basename
如果確切知道要移除的後綴,可以使用 basename。它的第二個參數只有在符合名稱結尾時才會移除該後綴。例如,basename "$file" .html 會將 annual.report.html 轉成 annual.report。如果名稱結尾是 .HTML 或其他後綴,.html 就不符合,因此會保留下來。為變數加上引號也能保護輸入中的空格。
basename 是外部命令;如果值已在 Bash 變數中,直接使用參數展開會更簡潔。當你需要的正是比對已知後綴的行為時,basename 就很實用。兩種方式都不會變更磁碟上的檔案。
使用 cut 處理分隔文字,不適合一般檔名後綴
cut 命令是用來從以分隔符號分隔的文字中選取欄位。使用 cut -d '.' -f 1 時,每一行輸入都會依句點切分,並只保留第一個欄位。如果你的規則是「保留第一個句點之前的文字」,這種方式可以用來處理清單。但它不適合一般的檔名副檔名移除:annual.report.html 會變成 annual,.report 和 .html 都會被移除。
若清單以換行分隔,可將文字傳入 cut,例如:printf '%s\n' "$file" | cut -d '.' -f 1。-d 選擇分隔符號,-f 1 則選取第一個欄位。只有在輸入資料確實依分隔符號組織,而且你要的正是該欄位時,才使用 cut。若要移除最後一個後綴,請改用 Bash 參數展開。
處理含多個句點的檔名並選擇合適方法
含有多個句點的檔名能清楚呈現不同方法的差異。對 archive.part.tar.gz 使用 ${file%.*} 只會移除 .gz,留下 archive.part.tar;若已知後綴是 .gz,basename "$file" .gz 也會得到相同結果;cut -d '.' -f 1 則只保留 archive。要移除最後一個後綴時選用參數展開;要移除已知後綴時使用 basename;需要依分隔符號選取欄位時才使用 cut。這些範例只會轉換檔名字串;若要重新命名檔案系統中的項目,必須另外執行操作。