9.Scripts
本章同步視頻:https://edu.51cto.com/sd/e4874
9.3 善用判斷式
9.3.1 利用 test和[ ] 的測試功能
當 test 判斷 expression 成立時,退出狀態爲 0,否則爲非 0 值。
注意[]和expression之間的空格,這兩個空格是必須的,否則會導致語法錯誤。
測試的標誌 | 代表意義 |
1. 關於某個檔名的『文件類型』判斷,如 test -e filename 表示存在否 | |
-e | 該『檔名』是否存在?(常用) |
-f | 該『檔名』是否存在且爲檔案(file)?(常用) |
-d | 該『文件名』是否存在且爲目錄(directory)?(常用) |
-b | 該『檔名』是否存在且爲一個 block device 裝置? |
-c | 該『檔名』是否存在且爲一個 character device 裝置? |
-S | 該『檔名』是否存在且爲一個 Socket 檔案? |
-p | 該『檔名』是否存在且爲一個 FIFO (pipe) 檔案? |
-L | 該『檔名』是否存在且爲一個連結檔? |
1.sh file20200426 hello.sh vmware-root
file20200425 file20200427 showname.sh
[root@localhost tmp]# test -e 1.sh #判斷1.sh是否存在
[root@localhost tmp]# test -e 2.sh #判斷2.sh是否存在
測試的標誌 | 代表意義 |
2. 關於檔案的權限偵測,如 test -r filename 表示可讀否 (但 root 權限常有例外) | |
-r | 偵測該檔名是否存在且具有『可讀』的權限? |
-w | 偵測該檔名是否存在且具有『可寫』的權限? |
-x | 偵測該檔名是否存在且具有『可執行』的權限? |
-u | 偵測該文件名是否存在且具有『SUID』的屬性? |
-g | 偵測該文件名是否存在且具有『SGID』的屬性? |
-k | 偵測該文件名是否存在且具有『Sticky bit』的屬性? |
-s | 偵測該檔名是否存在且爲『非空白檔案』? |
-rw-r--r--. 1 root root 450 Apr 27 06:16 1.sh
[root@localhost tmp]# test -r 1.sh #判斷1.sh是否可讀
[root@localhost tmp]# test -w 1.sh #判斷1.sh是否可寫
[root@localhost tmp]# test -x 1.sh #判斷1.sh是否可執行
測試的標誌 | 代表意義 |
3. 兩個檔案之間的比較,如: test file1 -nt file2 | |
-nt | (newer than)判斷 file1 是否比 file2 新 |
-ot | (older than)判斷 file1 是否比 file2 舊 |
-ef | 判斷 file1 與 file2 是否爲同一檔案,可用在判斷 hard link 的判定上。主要意義在判定,兩個檔案是否均指向同一個 inode 哩! |
[root@localhost tmp]# test 1.sh -nt hello.sh
測試的標誌 | 代表意義 |
4. 關於兩個整數之間的判定,例如 test n1 -eq n2 | |
-eq | 兩數值相等 (equal) |
-ne | 兩數值不等 (not equal) |
-gt | n1 大於 n2 (greater than) |
-lt | n1 小於 n2 (less than) |
-ge | n1 大於等於 n2 (greater than or equal) |
-le | n1 小於等於 n2 (less than or equal) |
[root@localhost tmp]# [ 5 -gt 9 ] #判斷5>9
測試的標誌 | 代表意義 |
5. 判定字符串的數據 | |
test -z string | 判定字符串是否爲 0 ?若 string 爲空字符串,則爲 true |
test -n string | 判定字符串是否非爲 0 ?若 string 爲空字符串,則爲 false。 注: -n 亦可省略 |
test str1 == str2 | 判定 str1 是否等於 str2 ,若相等,則回傳 true |
test str1 != str2 | 判定 str1 是否不等於 str2 ,若相等,則回傳 false |
[root@localhost tmp]# [ "abc" == "ABC" ] #判斷“abc”是否等於“ABC”
測試的標誌 | 代表意義 |
6. 多重條件判定,例如: test -r filename -a -x filename | |
-a | (and)兩狀況同時成立!例如 test -r file -a -x file,則 file 同時具有 r 與 x 權限時,纔回傳 true。 |
-o | (or)兩狀況任何一個成立!例如 test -r file -o -x file,則 file 具有 r 或 x 權限時,就可回傳 true。 |
! | 反相狀態,如 test ! -x file ,當 file 不具有 x 時,回傳 true |
[root@localhost tmp]# [ 2 -lt 5 ] && [ 5 -lt 10 ] #判斷2<5並且5<10
[root@localhost tmp]# [ 2 -lt 5 -a 5 -lt 10 ] #返回值爲0,表示1.sh可讀
-rw-r--r--. 1 root root 450 Apr 27 06:16 1.sh
[root@localhost tmp]# test -f 1.sh -a -r 1.sh #判斷1.sh是普通文件,並且可讀
[root@localhost tmp]# vim 1.sh
echo -e "Please input a filename, I will check the filename's type and permission. \n\n"
read -p "Input a filename : " filename
test -z ${filename} && echo "You MUST input a filename." && exit 0
##輸入檔名,並且判斷使用者是否真的有輸入字符串,如未輸入,則結束。
test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0
test -f ${filename} && filetype="regulare file" #是否是文件
test -d ${filename} && filetype="directory" #是否是目錄
test -r ${filename} && perm="readable" #是否可讀
test -w ${filename} && perm="${perm} writable" #是否可寫
test -x ${filename} && perm="${perm} executable" #是否可執行
echo "The filename: ${filename} is a ${filetype}" #輸出文件類型
echo "And the permissions for you are : ${perm}" #輸出文件權限
[root@localhost tmp]# ll hello.sh
-rw-r--r--. 1 root root 245 Apr 27 05:08 hello.sh
[root@localhost tmp]# chmod u+x 1.sh
[root@localhost tmp]# ./1.sh #正常運行
Please input a filename, I will check the filename's type and permission.
The filename: hello.sh is a regulare file
And the permissions for you are : readable writable
[root@localhost tmp]# ./1.sh #不輸入文件名
Please input a filename, I will check the filename's type and permission.
[root@localhost tmp]# ./1.sh #輸入錯誤的文件名
Please input a filename, I will check the filename's type and permission.
The filename '2.sh' DO NOT exist
[root@localhost tmp]# vim 1.sh
read -p "Please input (Y/N): " yn
[ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "OK, continue" && exit 0
[ "${yn}" == "N" ] || [ "${yn}" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0
9.3.2 [[ ]]
[[ ]]是 Shell 內置關鍵字,它和 test 命令類似,也用來檢測某個條件是否成立。test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 還能做到。可以認爲 [[ ]] 是 test 的升級版。[[ ]] 的用法爲:
當 [[ ]] 判斷 expression 成立時,退出狀態爲 0,否則爲非 0 值。注意[[ ]]和expression之間的空格,這兩個空格是必須的,否則會導致語法錯誤。
[[ ]] 是 Shell 內置關鍵字,不是命令,在使用時沒有給函數傳遞參數的過程,所以 test 命令的某些注意事項在 [[ ]] 中就不存在了,具體包括:
u 不需要把變量名用雙引號""包圍起來,即使變量是空值,也不會出錯。
[root@localhost tmp]# [ -z "$str1" ] || [ -z "$str2" ]
[root@localhost tmp]# [ -z "$str1" -o -z "$str2" ]
[root@localhost tmp]# [[ -z $str1 || -z $str2 ]]
[root@localhost tmp]# [[ -z $str1 -o -z $str2 ]]
bash: syntax error in conditional expression
#注:[[ ]] 剔除了 test 命令的-o和-a選項,你只能使用 || 和 &&。但可以寫成如下格式:
[root@localhost tmp]# [[ -z $str1 ]] || [[ -z $str2 ]]