test命令用法。功能:檢查文件和比較值node
1)判斷表達式 linux
if test (表達式爲真)shell
if test !表達式爲假數據庫
test 表達式1 –a 表達式2 兩個表達式都爲真express
test 表達式1 –o 表達式2 兩個表達式有一個爲真bash
2)判斷字符串併發
test –n 字符串 字符串的長度非零less
test –z 字符串 字符串的長度爲零函數
test 字符串1=字符串2 字符串相等工具
test 字符串1!=字符串2 字符串不等
3)判斷整數
test 整數1 –eq 整數2 整數相等
test 整數1 –ge 整數2 整數1大於等於整數2
test 整數1 –gt 整數2 整數1大於整數2
test 整數1 –le 整數2 整數1小於等於整數2
test 整數1 –lt 整數2 整數1小於整數2
test 整數1 –ne 整數2 整數1不等於整數2
4)判斷文件
test File1 –ef File2 兩個文件具備一樣的設備號和i結點號
test File1 –nt File2 文件1比文件2 新
test File1 –ot File2 文件1比文件2 舊
test –b File 文件存在而且是塊設備文件
test –c File 文件存在而且是字符設備文件
test –d File 文件存在而且是目錄
test –e File 文件存在
test –f File 文件存在而且是正規文件
test –g File 文件存在而且是設置了組ID
test –G File 文件存在而且屬於有效組ID
test –h File 文件存在而且是一個符號連接(同-L)
test –k File 文件存在而且設置了sticky位
test –b File 文件存在而且是塊設備文件
test –L File 文件存在而且是一個符號連接(同-h)
test –o File 文件存在而且屬於有效用戶ID
test –p File 文件存在而且是一個命名管道
test –r File 文件存在而且可讀
test –s File 文件存在而且是一個套接字
test –t FD 文件描述符是在一個終端打開的
test –u File 文件存在而且設置了它的set-user-id位
test –w File 文件存在而且可寫
test –x File 文件存在而且可執行
————————————————————————————————————————————————
每一種條件語句的基礎都是判斷什麼是真什麼是假。是否瞭解其工做原理將決定您編寫的是質量通常的腳本仍是您將引覺得榮的腳本。
Shell 腳本的能力時常被低估,但實際上其能力的發揮受制於腳本撰寫者的能力。您瞭解得越多,您就越能像變戲法似地撰寫一個文件來使任務自動化和簡化您的管理工做。
在 shell 腳本中進行的每一種操做(除最簡單的命令編組以外)都須要檢查條件。全部的 shell 腳本「邏輯」 — 廣義意義下的「邏輯」 — 一般均可以分爲如下三大類:
if {condition exists} then ...
while {condition exists} do ...
until {condition exists} do ...
不管隨後的操做是什麼,這些基於邏輯的命令都依靠判斷一種條件是否真實存在來決定後續的操做。test 命令是使得在每一種狀況下都可以肯定要判斷的條件是否存在的實用工具。所以,完全瞭解這個命令對於撰寫成功的 shell 腳本相當重要。
工做原理
test 命令最短的定義多是評估一個表達式;若是條件爲真,則返回一個 0 值。若是表達式不爲真,則返回一個大於 0 的值 — 也能夠將其稱爲假值。檢查最後所執行命令的狀態的最簡便方法是使用 $? 值。出於演示的目的,本文中的例子所有使用了這個參數。
test 命令指望在命令行中找到一個參數,當 shell 沒有爲變量賦值時,則將該變量視爲空。這意味着在處理腳本時,一旦腳本尋找的參數不存在,則 test 將報告該錯誤。
當試圖保護腳本時,您能夠經過將全部參數包含在雙引號中來解決這個問題。而後 shell 將變量展開,若是變量沒有值,那麼將傳遞一個空值給 test。另外一種方法是在腳本內增長一個額外檢查過程來判斷是否設置了命令行參數。若是沒有設置命令行參數,那麼腳本會告訴用戶缺乏參數,而後退出。咱們會經過一些例子來更具體地說明全部這些內容。
test 和 [ 命令
雖然 Linux 和 UNIX 的每一個版本中都包含 test 命令,但該命令有一個更經常使用的別名 — 左方括號:[。test 及其別名一般均可以在 /usr/bin 或 /bin (取決於操做系統版本和供應商)中找到。
當您使用左方括號而非 test 時,其後必須始終跟着一個空格、要評估的條件、一個空格和右方括號。右方括號不是任何東西的別名,而是表示所需評估參數的結束。條件兩邊的空格是必需的,這表示要調用 test,以區別於一樣常用方括號的字符/模式匹配操做。
test 和 [ 的語法以下:
test expression
[ expression ]
在這兩種狀況下,test 都評估一個表達式,而後返回真或假。若是它和 if、while 或 until 命令結合使用,則您能夠對程序流進行普遍的控制。不過,您無需將 test 命令與任何其它結構一塊兒使用;您能夠從命令行直接運行它來檢查幾乎任何東西的狀態。
由於它們彼此互爲別名,因此使用 test 或 [ 均須要一個表達式。表達式通常是文本、數字或文件和目錄屬性的比較,而且能夠包含變量、常量和運算符。運算符能夠是字符串運算符、整數運算符、文件運算符或布爾運算符 — 咱們將在如下各部分依次介紹每一種運算符。
test 文件運算符
利用這些運算符,您能夠在程序中根據對文件類型的評估結果執行不一樣的操做:
-b file 若是文件爲一個塊特殊文件,則爲真
-c file 若是文件爲一個字符特殊文件,則爲真
-d file 若是文件爲一個目錄,則爲真
-e file 若是文件存在,則爲真
-f file 若是文件爲一個普通文件,則爲真
-g file 若是設置了文件的 SGID 位,則爲真
-G file 若是文件存在且歸該組全部,則爲真
-k file 若是設置了文件的粘着位,則爲真
-O file 若是文件存在而且歸該用戶全部,則爲真
-p file 若是文件爲一個命名管道,則爲真
-r file 若是文件可讀,則爲真
-s file 若是文件的長度不爲零,則爲真
-S file 若是文件爲一個套接字特殊文件,則爲真
-t fd 若是 fd 是一個與終端相連的打開的文件描述符(fd 默認爲 1),則爲真
-u file 若是設置了文件的 SUID 位,則爲真
-w file 若是文件可寫,則爲真
-x file 若是文件可執行,則爲真
如下示例顯示了此簡單操做的運行狀況:
$ 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
$
因爲第一次評估爲真 — 文件存在且可讀 — 返回值爲真,或 0。因爲第二次評估的文件不存在,該值爲假,返回值不爲零。將值指定爲零或非零很重要,由於在失敗時不會始終返回 1(雖然這是一般返回的值),可能返回一個非零值。
正如開頭所提到的,除了使用 test 外,您還能夠用方括號 [ ] 將命令括住來向 shell 發出一樣的命令 — 以下所示:
$ [ -w evan ]
$ echo $?
0
$ [ -x evan ]
$ echo $?
1
$
一樣,第一個表達式爲真,第二個表達式爲假 — 正如返回值所指示的那樣。您還可使用如下命令將兩個文件彼此進行比較:
file1 -ef file2 測試以判斷兩個文件是否與同一個設備相連,是否擁有相同的 inode 編號
file1 -nt file2 測試以判斷第一個文件是否比第二個文件更新(由修改日期決定)
file1 -ot file2 測試以判斷第一個文件是否比第二個文件更舊
如下示例顯示了使用這些運算符比較文件的結果:
$ [ evan -nt spencer ]
$ echo $?
0
$ [ karen -ot spencer ]
$ echo $?
1
$
名爲 evan 的文件比名爲 spencer 的文件更新,於是評估爲真。相似地,名爲 karen 的文件比名爲 spencer 的文件更新,所以該評估爲假。
字符串比較運算符
如標題所示,這組函數比較字符串的值。您能夠檢查它們是否存在、是否相同或者是否不一樣。
String 測試以判斷字符串是否不爲空
-n string 測試以判斷字符串是否不爲空;字符串必須爲 test 所識別
-z string 測試以判斷字符串是否爲空;字符串必須爲 test 所識別
string1 = string2 測試以判斷 string1 是否與 string2 相同
string1 != string2 測試以判斷 string1 是否與 string2 不一樣
對任何變量進行的最有用的測試之一是判斷它的值是否不爲空,能夠簡單地將其放在 test 命令行中執行這種測試,以下例所示:
$ test "$variable"
強烈建議進行此種測試時用雙引號將變量括住,以讓 shell 識別變量(即便變量爲空)。默認狀況下執行的基本字符串評估和 -n 測試從功能上講是相同的,如如下示例所示:
#example1
if test -n "$1"
then
echo "$1"
fi
執行以上例子中的代碼將根據 $1 是否存在給出如下結果:
$ example1 friday
friday
$
$ example1
$
若是將代碼更改成如下形式,則結果將相同:
#example2
if test "$1"
then
echo "$1"
fi
以下所示:
$ example2 friday
friday
$
$ example2
$
全部這些代表,一般不須要 -n,它表明默認操做。
要從一個不一樣的角度來查看各類可能性,您能夠用另外一個選項來替換 -n,並檢查該值是否爲空(相對於非空)。這能夠用 -z 選項來實現,代碼爲:
#example3
if test -z "$1"
then
echo "no values were specified"
fi
運行以下:
$ example3
no values were specified
$ example3 friday
$
若是在沒有命令行參數的狀況下運行該程序,而表達式評估爲真,那麼將執行程序塊中的文本。若是在命令行中有值,則腳本退出,不執行任何操做。將評估操做放在腳本的開頭很是有用,這能夠在可能產生錯誤的進一步處理以前預先檢查變量值。
其他的字符串運算符對兩個變量/字符串之間的精確匹配或其中的差別(您也能夠稱之爲等價性和「不等價性」)進行評估。第一個例子對匹配進行測試:
$ env
LOGNAME=emmett
PAGER=less
SHELL=/bin/bash
TERM=linux
$
$ [ "$LOGNAME" = "emmett" ]
$ echo $?
0
$
$ [ "$LOGNAME" = "kristin" ]
$ echo $?
1
$
或者,該評估能夠以腳本的形式用於決定是否運行腳本:
#example4
if [ "$LOGNAME" = "emmett" ]
then
echo "processing beginning"
else
echo "incorrect user"
fi
這種方法能夠用來尋找任意的值(如終端類型或 shell 類型),在容許腳本運行以前這些值必須匹配。請注意,= 或 != 運算符的優先級高於其它大多數可指定選項,且要求必須伴有表達式。所以,除了比較字符串的選項以外,= 或 != 都不能和檢查某種東西(如可讀文件、可執行文件或目錄)的存在性的選項一塊兒使用。
整數比較運算符
正如字符串比較運算符驗證字符串相等或不一樣同樣,整數比較運算符對數字執行相同的功能。若是變量的值匹配則表達式測試爲真,若是不匹配,則爲假。整數比較運算符不處理字符串(正如字符串運算符不處理數字同樣):
int1 -eq int2 若是 int1 等於 int2,則爲真
int1 -ge int2 若是 int1 大於或等於 int2,則爲真
int1 -gt int2 若是 int1 大於 int2,則爲真
int1 -le int2 若是 int1 小於或等於 int2,則爲真
int1 -lt int2 若是 int1 小於 int2,則爲真
int1 -ne int2 若是 int1 不等於 int2,則爲真
如下示例顯示了一個代碼段,其中在命令行中給出的值必須等於 7:
#example5
if [ $1 -eq 7 ]
then
echo "You've entered the magic number."
else
echo "You've entered the wrong number."
fi
運行中:
$ example5 6
You've entered the wrong number.
$
$ example5 7
You've entered the magic number.
$
和字符串同樣,比較的值能夠是在腳本外爲變量賦的值,而沒必要老是在命令行中提供。如下示例演示了實現這一點的一種方法:
#example6
if [ $1 -gt $number ]
then
echo "Sorry, but $1 is too high."
else
echo "$1 will work."
fi
$ set number=7
$ export number
$ example6 8
Sorry, but 8 is too high.
$ example6 7
7 will work.
$
整數比較運算符最佳的用途之一是評估指定的命令行變量的數目,並判斷它是否符合所要求的標準。例如,若是某個特定的命令只能在有三個或更少變量的狀況下運行,
#example7 - display variables, up to three
if [ "$#" -gt 3 ]
then
echo "You have given too many variables."
exit $#
fi
只要指定三個或更少的變量,該示例腳本將正常運行(並返回值 0)。若是指定了三個以上的變量,則將顯示錯誤消息,且例程將退出 — 同時返回與命令行中給定的變量數相等的退出代碼。
對這個過程進行修改能夠用來在容許運行報表以前判斷當天是不是本月的最後幾天:
#example8 - to see if it is near the end of the month#
set `date` # use backward quotes
if [ "$3" -ge 21 ]
then
echo "It is close enough to the end of the month to proceed"
else
echo "This report cannot be run until after the 21st of the month"
exit $3
fi
在這個例子中,設置了六個變量(經過空格彼此分開):
$1 = Fri
$2 = Feb
$3 = 6
$4 = 08:56:30
$5 = EST
$6 = 2004
這些值能夠在腳本中使用,就像它們是在命令行中輸入的同樣。請注意,退出命令再次返回一個值 — 在這種狀況下,返回的值是從 $3 的值中獲得的日期。這一技巧在故障診斷時會很是有用 — 若是您認爲腳本應該運行而沒有運行,那麼請查看 $? 的值。
一種相似的想法多是撰寫一個只在每月的第三個星期三運行的腳本。第三個星期三必定在該月的 15 日到 21 日之間。使用 cron,您能夠調用腳本在 15 日到 21 日之間天天的一個指定時間運行,而後使用腳本的第一行檢查 $1(在設置日期以後)的值是否爲 Thu。若是爲 Thu,那麼執行剩下的腳本,若是不是,則退出。
而另外一個想法多是,只容許腳本在超過 6:00 p.m. (18:00),全部用戶都回家以後運行。只要撰寫腳本,使其在值低於 18 時退出,並經過使用如下命令來獲取時間(將其設爲 $1)
set `date +%H`
布爾運算符
布爾運算符在幾乎每種語言中的工做方式都相同 — 包括 shell 腳本。在 nutshell 中,它們檢查多個條件爲真或爲假,或者針對假的條件而不是真的條件採起操做。與 test 搭配使用的運算符有
! expr 若是表達式評估爲假,則爲真
expr1 -a expr2 若是 expr1 和 expr2 評估爲真,則爲真
expr1 -o expr2 若是 expr1 或 expr2 評估爲真,則爲真
能夠用 != 運算符代替 = 進行字符串評估。這是最簡單的布爾運算符之一,對 test 的正常結果取非。
其他兩個運算符中的第一個是 -a(即 AND)運算符。要使測試最終爲真,兩個表達式都必須評估爲真。若是任何一個評估爲假,則整個測試將評估爲假。例如,
$ env
HOME=/
LOGNAME=emmett
MAIL=/usr/mail/emmett
PATH=:/bin:/usr/bin:/usr/lbin
TERM=linux
TZ=EST5:0EDT
$
$ [ "$LOGNAME" = "emmett" -a "$TERM" = "linux" ]
$ echo $?
0
$
$ [ "LOGNAME" = "karen" -a "$TERM" = "linux" ]
$ echo $?
1
$
在第一個評估中,兩個條件都測試爲真(在一個 linux 終端上登陸的是 emmett),所以整個評估爲真。在第二個評估中,終端檢查正確但用戶不正確,所以整個評估爲假。
簡而言之,AND 運算符能夠確保代碼只在兩個條件都知足時才執行。相反,只要任何一個表達式測試爲真,OR (-o) 運算符即爲真。咱們來修改先前的例子,並將其放到一個腳本中來講明這一點:
#example9
if [ "$LOGNAME" = "emmett" -o "$TERM" = "linux" ]
then
echo "Ready to begin."
else
echo "Incorrect user and terminal."
fi
$ env
HOME=/
LOGNAME=emmett
MAIL=/usr/mail/emmett
PATH=:/bin:/usr/bin:/usr/lbin
TERM=linux
TZ=EST5:0EDT
$ example9
Ready to begin.
$
$ LOGNAME=karen
$ example9
Ready to begin.
$
在腳本第一次運行時,評估判斷用戶是否等於 emmett。若是發現用戶等於 emmett,則腳本轉至 echo 語句,並跳過其他的檢查。它從不檢查終端是否等於 linux,由於它只須要找到一條爲真的語句就可使整個運算爲真。在腳本第二次運行時,它判斷用戶不是 emmett,所以它將檢查並發現終端確實是 linux。因爲一個條件爲真,腳本如今轉至 echo 命令。爲了引出第二條消息,兩個條件都必須爲假。
在先前肯定時間是否爲月末的例子中,能夠執行相似的檢查來防止用戶試圖在週末運行腳本:
#example10 - Do not let the script run over the weekend#
set `date` # use backward quotes
if [ "$1" = "Sat" -o "$1" = "Sun" ]
then
echo "This report cannot be run over the weekend."
fi
一些有用的示例
示例 1:在腳本文件中出現的「邏輯」的最簡單的形式(如本文全部示例中所示)是「if ... then」語句。先前的一個代碼段檢查是否存在必定數量的變量,而後將這些變量回顯。假設咱們對此稍微作一些修改,好比咱們想回顯變量,而且每次回顯均減去最左邊的變量,以顯示一個倒的三角形。
雖然這聽起來很簡單,但實際並不是如此;這是您在執行大規模處理時想實現的方式:處理第一個變量、轉移、處理下一個變量……
出於演示的目的,能夠按如下方式撰寫腳本中的重要行:
#example11 - display declining variables, up to three
if [ "$#" -gt 3 ] # see if more than three variables are given
then
echo "You have given more than three variables."
exit
fi
echo $*
if test -n "$2"
then
shift
echo $*
fi
if test -n "$2"
then
shift
echo $*
fi
它將按如下方式執行:
$ example11 one
one
$
$ example11 one two
one two
two
$
$ example11 one two three
one two three
two three
three
$
$ example11 one two three four
You have given more than three variables.
$
出於檢查的目的將數量限制爲三個變量的緣由是減小在例子中要檢查的行數。一切都循序漸進地進行,雖然它使人難以置信地混亂;用戶因使用了超過程序依設計所能處理的變量數而獲得警告,且腳本退出。若是變量數爲 3 或更少,則運算的核心部分開始執行。
回顯變量,執行測試以查看另外一個變量是否存在。若是另外一個變量存在,則執行一次轉移,回顯該變量,執行另外一測試,等等。總共使用了 16 個有效行,而程序僅能處理不超過三個變量 — 很是混亂。假設消除變量數的限制,程序能夠處理任意數量的變量。通過一些修改,腳本被縮短(美化)了,並能處理任意數量的變量:
#example12 - display declining variables, any number
while [ "$#" -gt 0 ]
do
echo $*
shift
done
$ example12 1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
2 3 4 5 6 7 8 9 0
3 4 5 6 7 8 9 0
4 5 6 7 8 9 0
5 6 7 8 9 0
6 7 8 9 0
7 8 9 0
8 9 0
9 0
0
如今減小到只有 5 個有效行,且消除了第一個腳本三個變量的限制,並在運行時要更高效。
示例 2:不管什麼時候當在腳本內執行與處理相關的操做時,下一個操做將始終檢查上一操做的狀態,以確認它已成功完成。您能夠經過檢查 $? 的狀態並驗證它等於 0 來實現這一目的。例如,若是一個數據目錄是否能訪問很是重要,
#example13
TEMP=LST
cd $TEMP
if [ $?-ne 0 ]
then
echo "Data directory could not be found."
Exit
fi
處理錯誤
資源
下載針對 Linux 的 Oracle 數據庫 10g
Oracle 數據庫 10g 第 1 版 (10.1.0.2) 如今可用於 Linux x86 和 Linux Itanium 平臺;請在此從 OTN 上免費下載。
訪問 Linux 技術中心
收藏本頁,以獲取關於 Linux 系統管理員最佳應用的通常技術信息,以及關於 Oracle-on-Linux 產品羣的具體技術信息。
相關文章
Linux 相關技術文章的存檔
test 命令經常出現的錯誤事實上只有兩種類型。第一種是未使用正確的評估類型,例如將字符串變量與整型變量進行比較或者將帶填充的字符串與不帶填充的字符串進行比較。仔細評估您使用的變量將使您最終找到錯誤的根源,並讓您可以解決這些問題。
第二種錯誤類型包括將方括號誤認爲別名以外的某個東西。方括號與其內容之間必須有一個空格;不然,它們將不能解釋其中的對象。例如,
$ [ "$LOGNAME" -gt 9]
test:] missing
$
請注意,錯誤消息指示 test 存在問題,即便使用了別名 ]。這些問題很容易發現,由於錯誤消息準確地將這些問題顯示出來,而後您能夠增長必要的空格。
結論
要在 shell 腳本中構建邏輯,您必須添加條件語句。每一條這種語句的核心都是對條件的評估,以判斷它是否存在 — 經過使用 test 命令完成評估。瞭解它和它的別名(左方括號 ([)的工做原理將使您可以撰寫能夠完成一些複雜操做的 shell 腳本。