『忘了再學』Shell基礎 — 32、Shell中test測試命令詳解

1、test測試命令

(1)test命令介紹

在Shell中的test測試命令,用於測試某種條件或某幾種條件是否真實存在。

在Shell中的test測試命令,是判斷語句和循環語句中條件測試的工具。test命令經常用於對判斷語句進行測試,用於檢查某個條件是否成立,它可以進行數值、字元和文件三個方面的測試。

(2)test命令使用方式

Shell中test命令的用法有兩種:

  • 方式一:test expression
    test判斷expression成立時,返回值狀態為 0,否則為非 0 值。
    expression為表達式。
  • 方式二:test命令也可以簡寫為[ ]
    這時的test命令格式為:[ expression ]
    expression為表達式。
    注意:[]expression之間的空格,這兩個空格是必須的,否則會導致語法錯誤。[]的寫法更加簡潔,比 test使用頻率高。

(3)示例

需求:判斷一個文件是否存在。

# 說明:
# -e 選項是test命令中判斷文件是否存在的選項
# test命令用命令行的方式執行是沒有返回顯示的,
# 我們可以通過查看$?變數的方式,查看上一條命令是否正確執行。
# 返回值為0,表示上一條命令正確執行,
# 返回值為非0,表示上一條命令沒有正確執行。

# 判斷一個文件是否存在
# 方式一:
[root@localhost tmp]# test -e student.txt
# 結果為0,表示上一條命令正確執行,說明student.txt文件存在。
[root@localhost tmp]# echo $?
0

# 方式二:
[root@localhost tmp]# [ -e abc.txt ]
# 結果為非0,表示上一條命令沒有正確執行,說明abc.txt文件不存在。
[root@localhost tmp]# echo $?
1

# 如果不想每次執行完test命令,還要查看$?變數,來確定命令是否正確實行,
# 可以使用如下編寫方式:(方式一同理)
[root@localhost tmp]# [ -e abc.txt ] && echo yes || echo no
no
[root@localhost tmp]# [ -e student.txt ] && echo yes || echo no
yes

提示:在編寫Shell程式時,一般都是使用第二種書寫方式(沒見過不一般的情況)。

2、按照文件類型進行判斷

我們先來看看test可以進行哪些文件類型的判斷:

測試選項 作用
-b 文件 判斷該文件是否存在,並且是否為塊設備文件(是塊設備文件為真)。(少見)
-c 文件 判斷該文件是否存在,並且是否為字元設備文件(是字元設備文件為真)。(少見)
-d 文件 判斷該文件是否存在,並且是否為目錄文件(是目錄為真)。(常見)
-e 文件 判斷該文件是否存在(存在為真)。(常見)
-f 文件 判斷該文件是否存在,並且是否為普通文件(是普通文件為真)。(常見)
-L 文件 判斷該文件是否存在,並且是否為符號鏈接文件(是符號鏈接文件為真)。(常見)
-p 文件 判斷該文件是否存在,並且是否為管道文件(是管道文件為真)。(少見)
-s 文件 判斷該文件是否存在,並且是否為非空(非空為真)。
-S 文件 判斷該文件是否存在,並且是否為套接字文件(是套接字文件為真)。

示例:

Linux系統中tmp目錄下的文件,情況如下:

[root@localhost tmp]# ll
總用量 12
-rw-r--r--. 1 root root 371 10月 16 13:28 student.txt
-rw-r--r--. 1 root root 318 10月 14 18:03 test2.txt
-rw-r--r--. 1 root root  69 10月 16 17:39 test.txt

練習:

# 1.判斷student.txt文件是否為目錄
[root@localhost tmp]# [ -d student.txt ] && echo yes || echo no
no

# 2.判斷student.txt文件是否為普通文件
[root@localhost tmp]# [ -f student.txt ] && echo yes || echo no
yes

# 3.判斷student.txt文件是中內容是否為空
[root@localhost tmp]# [ -s student.txt ] && echo yes || echo no
yes

# 我們創建一個空文件,在判斷一次。
[root@localhost tmp]# touch abc
[root@localhost tmp]# [ -s abc ] && echo yes || echo no
no


# 注意:
# 用命令行執行命令的時候可以寫相對路徑,因為我在對應的文件夾當中。
# 而在編寫Shell腳本的時候,文件名一定要加上絕對路徑,要不然有可能找不到。

3、按照文件許可權進行判斷

test命令是非常完善的判斷命令,還可以判斷文件的許可權,我們通過下表來看看:

測試選項 作用
-r 文件 判斷該文件是否存在,並且是否該文件擁有讀許可權(有讀許可權為真)(常用)
-w 文件 判斷該文件是否存在,並且是否該文件擁有寫許可權(有寫許可權為真)(常用)
-x 文件 判斷該文件是否存在,並且是否該文件擁有執行許可權(有執行許可權為真)(常用)
-u 文件 判斷該文件是否存在,並且是否該文件擁有SUID許可權(有SUID許可權為真)(會用到)
-g 文件 判斷該文件是否存在,並且是否該文件擁有SGID許可權(有SGID許可權為真)(會用到)
-k 文件 判斷該文件是否存在,並且是否該文件擁有SBit許可權(有SBit許可權為真)

示例:

Linux系統中tmp目錄下的文件,情況如下:

[root@localhost tmp]# ll
總用量 12
-rw-r--r--. 1 root root 371 10月 16 13:28 student.txt
-rw-r--r--. 1 root root 318 10月 14 18:03 test2.txt
-rw-r--r--. 1 root root  69 10月 16 17:39 test.txt

練習:

# 1.查看tmp目錄student.txt是否有寫的許可權
# tmp目錄student.txt文件許可權如下:
# -rw-r--r--. 1 root root 371 10月 16 13:28 student.txt
[root@localhost tmp]# [ -w student.txt ] && echo yes || echo no
yes
# 上面證明在tmp目錄中student.txt文件存在,並擁有寫許可權。

# 注意:
# -w選項是分不清是所有者,所數組,和其他人誰有寫許可權的,
# 只要該文件任何一個身份中出現寫的許可權,-w選項的判斷就是正確的。
# 如果你非要判斷某一個身份是否有寫的許可權,
# 就需要我們自己手動把文件的許可權按需求截取下來,然後編寫程式來判斷。

# -r選項和-x選項同理。



# 2.判斷student.txt文件是否擁有SUID許可權
[root@localhost tmp]# [ -u student.txt ] && echo yes || echo no
no

# 可以看到student.txt文件沒有設置SUID許可權
# 我們接下來給student.txt文件設置一下SUID許可權

[root@localhost tmp]# chmod u+s student.txt

# 查看一下測試student.txt文件的許可權
[root@localhost tmp]# ll student.txt
-rwSr--r--. 1 root root 371 10月 16 13:28 student.txt

# 可以看到student.txt文件的許可權中多了一個大S許可權
# 關於SUID許可權相關內容可以點擊如下鏈接進行查看:
# //blog.csdn.net/Liuyuelinjiayou/article/details/107197846
# 接下來我們在判斷student.txt文件受否擁有SUID許可權
[root@localhost tmp]# [ -u student.txt ] && echo yes || echo no
yes

# 練習完成後,盡量儘快的還原文件,一般之後的練習使用。
[root@localhost tmp]# chmod u-s student.txt
[root@localhost tmp]# ll student.txt
-rw-r--r--. 1 root root 371 10月 16 13:28 student.txt

4、兩個文件之間進行比較

通過下表來看看如何進行兩個文件之間的比較(少用了解一下):

測試選項 作用
文件1 -nt 文件2 判斷文件1的修改時間是否比文件2的新(如果新則為真)。
文件1 -ot 文件2 判斷文件1的修改時間是否比文件2的舊(如果舊則為真)。
文件1 -ef 文件2 判斷文件1是否和文件2的Inode號一致,可以理解為兩個文件是否為同一個文件。這個用於判斷硬鏈接是很好的方法。

示例:

# 把tmp目錄下的student.txt文件,硬連接到root目錄下student文件。
# 也就是給tmp目錄下的student.txt文件創建一個硬連接,在root目錄下。
[root@localhost tmp]# ln /tmp/student.txt  /root/student

# 然後判斷/tmp/student.txt文件和/root/student文件是否為同一文件。
[root@localhost tmp]# [ /tmp/student.txt -ef /root/student ] && echo yes || echo no
yes
# 結果為是。

5、兩個整數之間比較

通過下表來學習下如何在兩個整數之間進行比較(常用):

測試選項 作用
整數1 -eq 整數2 判斷整數1是否和整數2相等(相等為真)
整數1 -ne 整數2 判斷整數1是否和整數2不相等(不相等為真)
整數1 -gt 整數2 判斷整數1是否大於整數2(大於為真)
整數1 -lt 整數2 判斷整數1是否小於整數2(小於為真)
整數1 -ge 整數2 判斷整數1是否大於等於整數2(大於等於為真)
整數1 -le 整數2 判斷整數1是否小於等於整數2(小於等於為真)

示例:

# 1.-eq等於
[root@localhost tmp]# [ 66 -eq 88 ] && echo yes || echo no
no

# 2.-lt小於
[root@localhost tmp]# [ 66 -lt 88 ] && echo yes || echo no
yes

# 3.-le小於等於
[root@localhost tmp]# [ 66 -le 88 ] && echo yes || echo no
yes

# 在Shell編程的時候,會把數值型變數引入條件判斷表達式中,
# 就不會是光突突的數字了。

6、字元串的判斷

通過下表我們來學習下字元串的判斷(常用):

測試選項 作用
-z 字元串 判斷字元串是否為空(為空返回真)
-n 字元串 判斷字元串是否為非空(非空返回真)
字元串1 == 字元串2 判斷字元串1是否和字元串2相等(相等返回真)
字元串1 != 字元串2 判斷字元串1是否和字元串2不相等(不相等返回真)

示例1:

# 判斷變數name是否為空
[root@localhost tmp]# [ -z "$name" ] && echo yes || echo no
yes

# 給變數name賦值
[root@localhost tmp]# name=Zhubj
# 因為不為空,所以返回no
[root@localhost tmp]# [ -z "$name" ] && echo yes || echo no
no

示例2:

# 給變數aa和變數bb賦值
[root@localhost tmp]# aa=Shell
[root@localhost tmp]# bb=Shell

# 判斷變數aa和變數bb是否相等
# 因為變數aa的值為"Shell",不等於字元串"bb",所以返回no。
[root@localhost tmp]# [ "$aa" == "bb" ] && echo yes || echo no
no

# 變數aa和變數bb的值都為"Shell",所以返回yes。
[root@localhost tmp]# [ "$aa" == "$bb" ] && echo yes || echo no
yes

提示:Shell中用==雙等號來比對兩個字元串是否相等(內容相同)。使用-eq來比對兩個整數是否相等。

7、多重條件判斷

通過下表來看看多重條件判斷是什麼樣子的(常用):

測試選項 作用
判斷1 -a 判斷2 邏輯與,判斷1和判斷2都成立,最終的結果才為真。
判斷1 -o 判斷2 邏輯或,判斷1和判斷2有一個成立,最終的結果就為真。
! 判斷 邏輯非,使原始的判斷式取反。

也就是說多重條件判斷就是,可以同時判斷多個條件,前邊的條件都可以。

示例1:

# 定義一個變數aa賦值並賦值66。
[root@localhost tmp]# aa=66

# 判斷變數aa是否有值,同時判斷變數aa的是否大於88。
# 因為變數aa的值不大於88,所以雖然第一個判斷值為真,返回的結果也是假。
[root@localhost tmp]# [ -n "$aa" -a "$aa" -gt 88 ] && echo "yes" || echo "no"
no


# 給變數aa重新賦個大於88的值,返回結果就是yes了。
[root@localhost tmp]# aa=99
[root@localhost tmp]# [ -n "$aa" -a "$aa" -gt 88 ] && echo "yes" || echo "no"
yes

示例2:

# 練習邏輯非
# 說明:
# "-n"選項是變數aa不為空,返回值就是真。
# 加入"!"之後,判斷值就會取反,所以當變數aa有值時,返回值是假.
# "!"+"-n"選項就和"-z"選項作用一樣了。
[root@localhost tmp]# aa=99
[root@localhost tmp]# [ ! -n "$aa" ] && echo "yes" || echo "no"
no

# 在定義一個沒有賦值的變數cc,返回結果就是yes。
[root@localhost tmp]# [ ! -n "$cc" ] && echo "yes" || echo "no"
yes


# 注意:"!"和"-n"選項之間必須加入空格,否則會報錯的。