1)判斷表達(dá)式
if test (表達(dá)式為真)
if test !表達(dá)式為假
test 表達(dá)式1 –a 表達(dá)式2 兩個(gè)表達(dá)式都為真
test 表達(dá)式1 –o 表達(dá)式2 兩個(gè)表達(dá)式有一個(gè)為真
2)判斷字符串
test –n 字符串 字符串的長(zhǎng)度非零
test –z 字符串 字符串的長(zhǎng)度為零
test 字符串1=字符串2 字符串相等
test 字符串1?。阶址? 字符串不等
3)判斷整數(shù)
test 整數(shù)1 –eq 整數(shù)2 整數(shù)相等
test 整數(shù)1 –ge 整數(shù)2 整數(shù)1大于等于整數(shù)2
test 整數(shù)1 –gt 整數(shù)2 整數(shù)1大于整數(shù)2
test 整數(shù)1 –le 整數(shù)2 整數(shù)1小于等于整數(shù)2
test 整數(shù)1 –lt 整數(shù)2 整數(shù)1小于整數(shù)2
test 整數(shù)1 –ne 整數(shù)2 整數(shù)1不等于整數(shù)2
4)判斷文件
test File1 –ef File2 兩個(gè)文件具有同樣的設(shè)備號(hào)和i結(jié)點(diǎn)號(hào)
test File1 –nt File2 文件1比文件2 新
test File1 –ot File2 文件1比文件2 舊
test –b File 文件存在并且是塊設(shè)備文件
test –c File 文件存在并且是字符設(shè)備文件
test –d File 文件存在并且是目錄
test –e File 文件存在
test –f File 文件存在并且是正規(guī)文件
test –g File 文件存在并且是設(shè)置了組ID
test –G File 文件存在并且屬于有效組ID
test –h File 文件存在并且是一個(gè)符號(hào)鏈接(同-L)
test –k File 文件存在并且設(shè)置了sticky位
test –b File 文件存在并且是塊設(shè)備文件
test –L File 文件存在并且是一個(gè)符號(hào)鏈接(同-h)
test –o File 文件存在并且屬于有效用戶ID
test –p File 文件存在并且是一個(gè)命名管道
test –r File 文件存在并且可讀
test –s File 文件存在并且是一個(gè)套接字
test –t FD 文件描述符是在一個(gè)終端打開的
test –u File 文件存在并且設(shè)置了它的set-user-id位
test –w File 文件存在并且可寫
test –x File 文件存在并且可執(zhí)行
每一種條件語(yǔ)句的基礎(chǔ)都是判斷什么是真什么是假。是否了解其工作原理將決定您編寫的是質(zhì)量一般的腳本還是您將引以為榮的腳本。
Shell 腳本的能力時(shí)常被低估,但實(shí)際上其能力的發(fā)揮受制于腳本撰寫者的能力。您了解得越多,您就越能像變戲法似地撰寫一個(gè)文件來(lái)使任務(wù)自動(dòng)化和簡(jiǎn)化您的管理工作。
在 shell 腳本中進(jìn)行的每一種操作(除最簡(jiǎn)單的命令編組之外)都需要檢查條件。所有的 shell 腳本“邏輯” — 廣義意義下的“邏輯” — 通常都可以分為以下三大類:while {condition exists} do ...
until {condition exists} do ...
無(wú)論隨后的操作是什么,這些基于邏輯的命令都依靠判斷一種條件是否真實(shí)存在來(lái)決定后續(xù)的操作。test 命令是使得在每一種情況下都能夠確定要判斷的條件是否存在的實(shí)用工具。因此,徹底了解這個(gè)命令對(duì)于撰寫成功的 shell 腳本至關(guān)重要。
工作原理
test 命令最短的定義可能是評(píng)估一個(gè)表達(dá)式;如果條件為真,則返回一個(gè) 0 值。如果表達(dá)式不為真,則返回一個(gè)大于 0 的值 — 也可以將其稱為假值。檢查最后所執(zhí)行命令的狀態(tài)的最簡(jiǎn)便方法是使用 $? 值。出于演示的目的,本文中的例子全部使用了這個(gè)參數(shù)。
test 命令期望在命令行中找到一個(gè)參數(shù),當(dāng) shell 沒有為變量賦值時(shí),則將該變量視為空。這意味著在處理腳本時(shí),一旦腳本尋找的參數(shù)不存在,則 test 將報(bào)告該錯(cuò)誤。
當(dāng)試圖保護(hù)腳本時(shí),您可以通過將所有參數(shù)包含在雙引號(hào)中來(lái)解決這個(gè)問題。然后 shell 將變量展開,如果變量沒有值,那么將傳遞一個(gè)空值給 test。另一種方法是在腳本內(nèi)增加一個(gè)額外檢查過程來(lái)判斷是否設(shè)置了命令行參數(shù)。如果沒有設(shè)置命令行參數(shù),那么腳本會(huì)告訴用戶缺少參數(shù),然后退出。我們 會(huì)通過一些例子來(lái)更具體地說明所有這些內(nèi)容。
test 和 [ 命令
雖然 Linux 和 UNIX 的每個(gè)版本中都包含 test 命令,但該命令有一個(gè)更常用的別名 — 左方括號(hào):[。test 及其別名通常都可以在 /usr/bin 或 /bin (取決于操作系統(tǒng)版本和供應(yīng)商)中找到。
當(dāng)您使用左方括號(hào)而非 test 時(shí),其后必須始終跟著一個(gè)空格、要評(píng)估的條件、一個(gè)空格和右方括號(hào)。右方括號(hào)不是任何東西的別名,而是表示所需評(píng)估參數(shù)的結(jié)束。條件兩邊的空格是必需的,這表示要調(diào)用 test,以區(qū)別于同樣經(jīng)常使用方括號(hào)的字符/模式匹配操作。
test 和 [ 的語(yǔ)法如下:
test expression
[ expression ]
在這兩種情況下,test 都評(píng)估一個(gè)表達(dá)式,然后返回真或假。如果它和 if、while 或 until 命令結(jié)合使用,則您可以對(duì)程序流進(jìn)行廣泛的控制。不過,您無(wú)需將 test 命令與任何其它結(jié)構(gòu)一起使用;您可以從命令行直接運(yùn)行它來(lái)檢查幾乎任何東西的狀態(tài)。
因?yàn)樗鼈儽舜嘶閯e名,所以使用 test 或 [ 均需要一個(gè)表達(dá)式。表達(dá)式一般是文本、數(shù)字或文件和目錄屬性的比較,并且可以包含變量、常量和運(yùn)算符。運(yùn)算符可以是字符串運(yùn)算符、整數(shù)運(yùn)算符、文件運(yùn)算符或布爾運(yùn)算符 — 我們將在以下各部分依次介紹每一種運(yùn)算符。
test 文件運(yùn)算符
利用這些運(yùn)算符,您可以在程序中根據(jù)對(duì)文件類型的評(píng)估結(jié)果執(zhí)行不同的操作:
-b file 如果文件為一個(gè)塊特殊文件,則為真
-c file 如果文件為一個(gè)字符特殊文件,則為真
-d file 如果文件為一個(gè)目錄,則為真
-e file 如果文件存在,則為真
-f file 如果文件為一個(gè)普通文件,則為真
-g file 如果設(shè)置了文件的 SGID 位,則為真
-G file 如果文件存在且歸該組所有,則為真
-k file 如果設(shè)置了文件的粘著位,則為真
-O file 如果文件存在并且歸該用戶所有,則為真
-p file 如果文件為一個(gè)命名管道,則為真
-r file 如果文件可讀,則為真
-s file 如果文件的長(zhǎng)度不為零,則為真
-S file 如果文件為一個(gè)套接字特殊文件,則為真
-t fd 如果 fd 是一個(gè)與終端相連的打開的文件描述符(fd 默認(rèn)為 1),則為真
-u file 如果設(shè)置了文件的 SUID 位,則為真
-w file 如果文件可寫,則為真
-x file 如果文件可執(zhí)行,則為真
$ ls -l
total 33
drwxr-xr-w 2 root root 1024 Dec 5 05:05 LST
-rw-rw-rw- 1 emmett users 27360 Feb 6 07:30 evan
-rwsrwsrwx 1 root root 152 Feb 6 07:32 hannah
drwxr-xr-x 2 emmett users 1024 Feb 6 07:31 karen
-rw------- 1 emmett users 152 Feb 6 07:29 kristin
-rw-r--r-- 1 emmett users 152 Feb 6 07:29 spencer
$
$ test -r evan
$ echo $?
0
$ test -r walter
$ echo $?
1
$
由于第一次評(píng)估為真 — 文件存在且可讀 — 返回值為真,或 0。由于第二次評(píng)估的文件不存在,該值為假,返回值不為零。將值指定為零或非零很重要,因?yàn)樵谑r(shí)不會(huì)始終返回 1(雖然這是通常返回的值),可能返回一個(gè)非零值。
正如開頭所提到的,除了使用 test 外,您還可以用方括號(hào) [ ] 將命令括住來(lái)向 shell 發(fā)出同樣的命令 — 如下所示:
$ [ -w evan ]
$ echo $?
0
$ [ -x evan ]
$ echo $?
1
$
同樣,第一個(gè)表達(dá)式為真,第二個(gè)表達(dá)式為假 — 正如返回值所指示的那樣。您還可以使用以下命令將兩個(gè)文件彼此進(jìn)行比較:
file1 -ef file2 測(cè)試以判斷兩個(gè)文件是否與同一個(gè)設(shè)備相連,是否擁有相同的 inode 編號(hào)
file1 -nt file2 測(cè)試以判斷第一個(gè)文件是否比第二個(gè)文件更新(由修改日期決定)
file1 -ot file2 測(cè)試以判斷第一個(gè)文件是否比第二個(gè)文件更舊
以下示例顯示了使用這些運(yùn)算符比較文件的結(jié)果:
$ [ evan -nt spencer ]
$ echo $?
0
$ [ karen -ot spencer ]
$ echo $?
1
$
名為 evan 的文件比名為 spencer 的文件更新,因而評(píng)估為真。類似地,名為 karen 的文件比名為 spencer 的文件更新,因此該評(píng)估為假。
字符串比較運(yùn)算符
如標(biāo)題所示,這組函數(shù)比較字符串的值。您可以檢查它們是否存在、是否相同或者是否不同。
String 測(cè)試以判斷字符串是否不為空
-n string 測(cè)試以判斷字符串是否不為空;字符串必須為 test 所識(shí)別
-z string 測(cè)試以判斷字符串是否為空;字符串必須為 test 所識(shí)別
string1 = string2 測(cè)試以判斷 string1 是否與 string2 相同
string1 != string2 測(cè)試以判斷 string1 是否與 string2 不同
對(duì)任何變量進(jìn)行的最有用的測(cè)試之一是判斷它的值是否不為空,可以簡(jiǎn)單地將其放在 test 命令行中執(zhí)行這種測(cè)試,如下例所示:
$ test "$variable"
強(qiáng)烈建議進(jìn)行此種測(cè)試時(shí)用雙引號(hào)將變量括住,以讓 shell 識(shí)別變量(即使變量為空)。默認(rèn)情況下執(zhí)行的基本字符串評(píng)估和 -n 測(cè)試從功能上講是相同的,如以下示例所示:
#example1
if test -n "$1"
then
echo "$1"
fi
執(zhí)行以上例子中的代碼將根據(jù) $1 是否存在給出以下結(jié)果:
$ example1 friday
friday
$
$ example1
$
如果將代碼更改為以下形式,則結(jié)果將相同:
#example2
if test "$1"
then
echo "$1"
fi
如下所示:
$ example2 friday
friday
$
$ example2
$
所有這些表明,通常不需要 -n,它代表默認(rèn)操作。
要從一個(gè)不同的角度來(lái)查看各種可能性,您可以用另一個(gè)選項(xiàng)來(lái)替換 -n,并檢查該值是否為空(相對(duì)于非空)。這可以用 -z 選項(xiàng)來(lái)實(shí)現(xiàn),代碼為:
#example3
if test -z "$1"
then
echo "no values were specified"
fi
運(yùn)行如下:
$ example3
no values were specified
$ example3 friday
$
如果在沒有命令行參數(shù)的情況下運(yùn)行該程序,而表達(dá)式評(píng)估為真,那么將執(zhí)行程序塊中的文本。如果在命令行中有值,則腳本退出,不執(zhí)行任何操作。將評(píng)估操作放在腳本的開頭非常有用,這可以在可能產(chǎn)生錯(cuò)誤的進(jìn)一步處理之前預(yù)先檢查變量值
聯(lián)系客服