shell 中兩種與文件名相關(guān)的展開(kāi)。第一種是波浪號(hào)展開(kāi),第二種是通配符展開(kāi)式。
波浪號(hào)展開(kāi)
如果命令行字符串的第一個(gè)字符為波浪號(hào) (~),或者變量指定 (例如 PATH 或 CDPATH 變量) 的值里任何未被引號(hào)括起來(lái)的冒號(hào)之后的第一個(gè)字符為波浪號(hào) (~) 時(shí),shell 變回執(zhí)行波浪號(hào)展開(kāi)。
波浪號(hào)展開(kāi)的目的,將用戶根目錄的符號(hào)型表示方式,改為實(shí)際的目錄路徑??梢圆捎弥苯踊蜷g接的方式指定執(zhí)行此程序的用戶,如未明白指定,則為當(dāng)前的用戶:
vi ~/.profile 與 vi $HOME/.profile 相同vi ~root/.profile 編輯用戶 root 的.profile 文件案例分析:第一個(gè)命令,shell 將 ~ 換成 $HOME,也就是當(dāng)前用戶的根目錄。第二個(gè)命令,則是 shell 在系統(tǒng)的密碼庫(kù)里,需找用戶 root,再將 ~root 置換為 root 的根目錄。
使用波浪號(hào)的好處:
有一段 bash 腳本:
printf "enter username :"
read user
vi /home/$user/.profile 編輯該用戶的.profile 文件
這段程序假設(shè)所有用戶的根目錄都在 /home 之下。如果這又任何變動(dòng) (例如,用戶子目錄根據(jù)部門(mén)存放在部門(mén)目錄的子目錄下),那么這個(gè)腳本就得重寫(xiě)。但如果使用波浪號(hào)展開(kāi),就能避免重寫(xiě)的情況:
printf "enter username :"
read user
vi /home/$user/.profile 編輯該用戶的.profile 文件
這樣一來(lái),無(wú)論用戶的根目錄在哪里,程序都能正常運(yùn)行了。
使用通配符
尋找文件名里的特殊字符,也是 shell 提供的服務(wù)之一。
基本的通配符
通配符
匹配
*
任何的字符串字符
[set]
任何在 set 里的字符
[!set]
任何不在 set 里的字符
?
任何的單一字符
? 通配符匹配于任何的單一字符,所以如果你的目錄里含有 demo.a,demo.b,demo.txt 這三個(gè)文件,與表達(dá)式 demo.? 匹配為 demo.a,demo.b,但是 demo.txt 則不匹配。(*) 是一個(gè)功能強(qiáng)大的且廣為使用的通配符;它匹配于任何字符組成的字符串。使用表達(dá)式 demo.* 會(huì)匹配前面說(shuō)的三個(gè)文件;網(wǎng)頁(yè)設(shè)計(jì)人員也可以用 *.html 表達(dá)式匹配他們的輸入文件。set 結(jié)構(gòu)是一組組字符列表 (例如 abc),一段內(nèi)含的范圍 (如 a-z),或者是兩者的結(jié)合。如果希望破折號(hào)也是列表的一部分,只要把它放在第一個(gè)或最后一個(gè)就可以了。
使用 set 結(jié)構(gòu)的通配符
表達(dá)式
匹配的單一字符
[abc]
a,b 或 c
[.,;]
句號(hào),逗號(hào),或分號(hào)
[-_]
破折號(hào)或下劃線
[a-c]
a,b 或 c
[a-z]
任意一個(gè)小寫(xiě)字母
[!0-9]
任意一個(gè)非數(shù)字字符
[0-9!]
任意一個(gè)數(shù)字會(huì)感嘆號(hào)
[a-zA-Z]
任意一個(gè)大寫(xiě)或小寫(xiě)字母
[a-zA-Z0_9_-]
任何一個(gè)字母,任何一個(gè)數(shù)字,下劃線或破折號(hào)
demo.[ab] 與 demo.[a-z] 兩者都匹配 demo.a 和 demo.b,但是 demo.txt 則不匹配。[!.;] 符合句號(hào)和分號(hào)以外的任何一個(gè)字符;[!a-zA-Z] 符合任何一個(gè)非字母的字符。范圍表示法固然方便,但不應(yīng)該對(duì)包含在范圍內(nèi)的字符有太多的假設(shè)。比較安全的方式是:分別指定所有大寫(xiě)字母,小寫(xiě)字母,數(shù)字,或任意的子范圍 (例如 [f-q].[2-6])。不要想在標(biāo)點(diǎn)符號(hào)字符上指定范圍,或是在混用字母大小寫(xiě)上使用,像 [a-Z] 與 [A-z] 這樣的用法,都不能保證一定能確切的匹配出包括所有想要的字母,而沒(méi)有其他不想要的字符。更大的問(wèn)題是在于:這樣的范圍在不同的類型之間的計(jì)算機(jī)之間無(wú)法提供完全的可移植性。
另一個(gè)問(wèn)題是:很多國(guó)家默認(rèn)的系統(tǒng)語(yǔ)言環(huán)境與純粹的 ASCII 的字符集是不同的。為了解決這個(gè)問(wèn)題,POSIX 標(biāo)準(zhǔn)提出了方括號(hào)表達(dá)式,用來(lái)表示字母,數(shù)字,標(biāo)點(diǎn)符號(hào)以及其他類型的字符,并且具有可移植性。在正則表達(dá)式下的方括號(hào)表達(dá)式里也出現(xiàn)相同的元素,它們可被用在兼容 POSIX 的 shell 內(nèi)的 shell 通配符模式中,不過(guò)應(yīng)該盡量避免將其應(yīng)用在需可移植的 shell 腳本里。
習(xí)慣上,當(dāng)執(zhí)行通配符展開(kāi)時(shí),linux shell 會(huì)忽略文件名開(kāi)頭為一個(gè)點(diǎn)號(hào)的文件。像這樣的“點(diǎn)號(hào)文件” 通常用做程序配置文件或啟動(dòng)文件 (一般都隱藏起來(lái)了,需要使用 ls -a 來(lái)查看)。像是 shell 的 $HOME/.profile,ex/vi 編輯器的 $HOME/.exrc,以及 bash 與 gdb 使用的 GNU readline 程序庫(kù)的 $HOME/.inputrc。
要看到這類文件,需要在模式前面明確的提供一個(gè)點(diǎn)號(hào)。例如:
echo .* 顯示隱藏文件
注意:隱藏文件只是一個(gè)習(xí)慣用法。在用戶層面的軟件上他是這樣的,但核心程序 (kernel) 并不認(rèn)為開(kāi)頭帶有一個(gè)點(diǎn)號(hào)的文件與其他文件有不同。