Linux test命令的用法(非常详细)
test 命令是 Bash 中重要的判断命令,也是 shell 脚本中条件判断的重要辅助工具。当我们需要让程序自动判断哪些事情是成立的时,test 命令就派上用场了。
test命令按照文件类型进行判断
根据下表,我们先来看看 test 命令可以进行哪些文件类型的判断。
举个例子来说明上表中判断式的含义,先来判断一下我们的 root 用户家目录 /root/ 是否存在,命令如下:
其实 test 命令就是这样的,但是应该如何判断这条命令的执行是否正确呢?还记得“$?”预定义变量吗?可以根据“$?”的值来确认条件判断是否成立,如果变量值为 0,就代表 test 判断为真;如果变量值为非 0,就代表 test 判断为假。
例如:
不过,这样来查看命令的结果的方式非常烦琐,也不直观。还记得多命令顺序执行符“&&”和“||”吗?我们可以再判断一下 /root/sh/ 是不是目录,命令如下:
在使用 test 命令判断权限时,是以当前用户身份进行判断的,因此建议使用普通用户进行权限判断练习,root 用户的权限过大。
例如:
我们一直很苦恼,到底该如何判断两个文件之间是不是硬链接关系呢?这时 -ef 就派上用场了,命令如下:
例如:
例如:
再来看点如何判断两个字符串相等,命令如下:
例如:
若想让刚刚的判断式返回真,则需要给变量 aa 重新赋一个大于 23 的值,命令如下:
再来看看逻辑非是什么样的,命令如下:
接下来举例说明。
注意,变量名是可以不加双引号的,但在判断含有空格的字符串时,判断式等号右边的字符串本身要使用双引号来表示为整体。
需要注意的是,等号右边的字符串不要使用双引号(或单引号)包含,因为在双引号(或单引号)中的通配或正则不生效。
当想要判断某字符串的行首字符或行尾字符时,可以选择使用“=~”作为判断符号,因为在使用“=~”作为判断符号时可以进行正则匹配。
还可以同时判断字符串开头的字符:
test命令按照文件类型进行判断
根据下表,我们先来看看 test 命令可以进行哪些文件类型的判断。
测试选项 | 作用 |
---|---|
-b 文件 | 判断该文件是否存在,并且是否为块设备文件(块设备文件为真) |
-c 文件 | 判断该文件是否存在,并且是否为字符设备文件(字符设备文件为真) |
-d 文件 | 判断该文件是否存在,并且是否为目录文件(目录文件为真) |
-e 文件 | 判断该文件是否存在(存在为真) |
-f 文件 | 判断该文件是否存在,并且是否为普通文件(普通文件为真) |
-L 文件 | 判断该文件是否存在,并且是否为符号链接文件(符号链接文件为真) |
-p 文件 | 判断该文件是否存在,并且是否为管道文件(管道文件为真) |
-s 文件 | 判断该文件是否存在,并且是否为非空(非空为真) |
-S 文件 | 判断该文件是否存在,并且是否为套接字文件(套接字文件为真) |
举个例子来说明上表中判断式的含义,先来判断一下我们的 root 用户家目录 /root/ 是否存在,命令如下:
[root@localhost ~]# test -e /root/这条命令也可以这样写:
[root@localhost ~]# [ -e /root ]它们的作用是一样的,推荐使用“[]”方式,因为在脚本的条件语句中主要应用“[]”方式。不过需要注意,如果使用“[]”方式,那么在“[]”的内部和数据之间必须使用空格,否则判断式会报错。
其实 test 命令就是这样的,但是应该如何判断这条命令的执行是否正确呢?还记得“$?”预定义变量吗?可以根据“$?”的值来确认条件判断是否成立,如果变量值为 0,就代表 test 判断为真;如果变量值为非 0,就代表 test 判断为假。
例如:
[root@localhost ~]# [ -e /root/sh ] [root@localhost ~]# echo $? 0 #如果判断结果为0,就证明/root/sh/目录存在 [root@localhost ~]# [ -e /root/test ] [root@localhost ~]# echo $? 1 #如果在/root/中没有test文件或目录,那么“$?”的返回值为非0
不过,这样来查看命令的结果的方式非常烦琐,也不直观。还记得多命令顺序执行符“&&”和“||”吗?我们可以再判断一下 /root/sh/ 是不是目录,命令如下:
[root@localhost ~]# [ -d /root/sh ] && echo "yes" || echo "no" #第一条判断命令如果正确执行,就打印“yes”,否则打印“no” yes这样就直观多了,不过也并不方便。等学习完条件判断,就会知道test判断的具体应用场景了。
test命令按照文件权限进行判断
test 是非常完善的判断命令,可以用来判断文件的权限,如下表所示:测试选项 | 作用 |
---|---|
-r 文件 | 判断该文件是否存在,并且是否拥有读权限(有读权限为真) |
-w 文件 | 判断该文件是否存在,并且是否拥有写权限(有写权限为真) |
-x 文件 | 判断该文件是否存在,并且是否拥有执行权限(有执行权限为真) |
-u 文件 | 判断该文件是否存在,并且是否拥有SUID权限(有SUID权限为真) |
-g 文件 | 判断该文件是否存在,并且是否拥有SGID权限(有SGID权限为真) |
-k 文件 | 判断该文件是否存在,并且是否拥有SBIT权限(有SBIT权限为真) |
在使用 test 命令判断权限时,是以当前用户身份进行判断的,因此建议使用普通用户进行权限判断练习,root 用户的权限过大。
例如:
[user@localhost ~]$ ls -ld /etc/ drwxr-xr-x. 78 root root 8192 Feb 19 17:45 /etc/ #user1用户登录,查看/etc/目录权限 [user@localhost ~]$ ls -ld /root/ dr-xr-x--- 2 root root 4096 Feb 19 17:15 /root/ #查看/root/目录权限 [user@localhost ~]$ id uid=1000(user1) gid=1000(user1) groups=1000(user1) ...省略部分内容... #查看user1用户身份、所属组情况 [user@localhost ~]$ [ -r /etc/ ] [user@localhost ~]$ echo $? 0 #user1用户属于/etc/目录的其他人,拥有读权限,判断结果为真 [user@localhost ~]$ [ -r /root/ ] [user@localhost ~]$ echo $? 1 #user1用户属于/root/目录其他人,没有读权限,判断结果不为真
test命令对两个文件进行比较
通过下表来看看如何在两个文件之间进行比较。测试选项 | 作用 |
---|---|
文件1 -nt 文件2 | 判断文件 1 的修改时间是否比文件 2 的新(如果新就为真) |
文件1 -ot 文件2 | 判断文件 1 的修改时间是否比文件 2 的旧(如果旧就为真) |
文件1 -ef 文件2 | 判断文件 1 是否和文件 2 的 inode 号一致,可以理解为判断两个文件是否为同一个文件。 |
我们一直很苦恼,到底该如何判断两个文件之间是不是硬链接关系呢?这时 -ef 就派上用场了,命令如下:
[root@localhost ~]# ln /root/student.txt /tmp/stu.txt #创建一个硬链接 [root@localhost ~]# [ /root/student.txt -ef /tmp/stu.txt ] && echo "yes" || echo "no" yes #使用test测试一下,输出为yes,证明两个文件之间是硬链接关系
test命令对两个整数进行比较
通过下表来学习一下如何在两个整数之间进行比较:测试选项 | 作用 |
---|---|
整数 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(小于等于为真) |
例如:
[root@localhost ~]# [ 24 -ge 23 ] && echo "yes" || echo "no" yes #判断 24 是否大于等于 23,判断成立 [root@localhost ~]# [ 23 -le 22 ] && echo "yes" || echo "no" no #判断 23 是否小于等于 22,判断不成立
test命令字符串判断
通过下表来学习一下字符串判断。测试选项 | 作用 |
---|---|
-z 字符串 | 判断字符串是否为空(为空返回真) |
-n 字符串 | 判断字符串是否为非空(非空返回真) |
字符串 1 = 字符串 2 | 判断字符串 1 是否和字符串 2 相等(相等返回真) |
字符串 1 != 字符串 2 | 判断字符串 1 是否和字符串 2 不相等(不相等返回真) |
例如:
[root@localhost ~]# var1=rs #给 var1 变量赋值 [root@localhost ~]# [ -z "$var1" ] && echo "yes" || echo "no" no #判断 var1 变量是否为空,因为不为空,所以返回 no
再来看点如何判断两个字符串相等,命令如下:
[root@localhost ~]# var2=rc [root@localhost ~]# var3=dl #给变量 var2 和变量 var3 赋值 [root@localhost ~]# [ "$var2" == "$var3" ] && echo "yes" || echo "no" no #判断两个变量的值是否相等(按照字符串判断),明显不相等,因此返回 no
test命令多重条件判断
通过下表来学习使用多重条件判断式的结构:测试选项 | 作用 |
---|---|
判断 1 -a 判断 2 | 逻辑与,判断 1 和判断 2 都成立,最终的结果才为真 |
判断 1 -o 判断 2 | 逻辑或,判断 1 和判断 2 有一个成立,最终的结果就为真 |
! 判断 | 逻辑非,使原始的判断式取反 |
例如:
[root@localhost ~]# aa=11 #给变量 aa 赋值 [root@localhost ~]# [ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no" no #判断变量 aa 是否有值,同时判断变量 aa 的值是否大于 23, #因为变量 aa 的值不大于 23,所以虽然第一个判断值为真,但是返回的结果为假
若想让刚刚的判断式返回真,则需要给变量 aa 重新赋一个大于 23 的值,命令如下:
[root@localhost ~]# aa=24 [root@localhost ~]# [ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no" yes
再来看看逻辑非是什么样的,命令如下:
[root@localhost ~]# [ ! -n "$aa" ] && echo "yes" || echo "no" no #本来 “-n” 选项是变量 aa 不为空,返回值为真 #在加入 “!” 之后,判断值就会取反,因此当变量 aa 有值时,返回值为假
注意:“!”和“-n”之间必须加入空格,否则会报错。
test命令[[][]]判断
在当前 Rocky Linux 9.2 中,还可以使用 [[][]] 来进行判断,相较于 [],除基础的判断能力外,其可以使用“&&”和“||”,代替 -a 逻辑与,以及 -o 逻辑或进行多重条件判断,可以判断带空格的变量值,可以在判断过程中使用通配符或正则表达式进行判断。接下来举例说明。
1) 逻辑与和逻辑或
[root@localhost ~]# x=24 #将变量 x 赋值为 24 [root@localhost ~]# [[ "$x" -gt 3 && "$x" -lt "100" ]] [root@localhost ~]# echo $? 0 #对 x 变量值进行多重条件判断,多重条件之间使用 "&&" 作为逻辑与判断 [root@localhost ~]# [[ "$x" -gt "3" || "$x" -lt "1" ]] [root@localhost ~]# echo $? 0 #对 x 变量值进行多重条件判断,多重条件之间使用 "||" 作为逻辑或判断
2) 含有空格的字符串判断
[root@localhost ~]# sys="rocky linux" #对 sys 进行赋值 [root@localhost ~]# [ $sys == "rocky linux" ] -bash: [: too many arguments #如果使用[]进行判断,那么在调用$sys的值时,若外侧没有双引号,则会出现报错的情况 [root@localhost ~]# [[ $sys == "rocky linux" ]] #使用[]进行判断,同样不加双引号,调用$sys的值不会出现报错 [root@localhost ~]# echo $? 0 #判断成立如果使用 [] 对含有空格的字符串进行判断,那么通常需要先进行列截取,再逐列进行判断。如果使用 [[]] 对调用包含空格的值进行判断,就省去了列截取的过程。
注意,变量名是可以不加双引号的,但在判断含有空格的字符串时,判断式等号右边的字符串本身要使用双引号来表示为整体。
3) 匹配字符串或正则
在进行字符串匹配(或正则)时需要将变量名写在等号左边,包含通配(或正则)的判断条件写在等号右边。需要注意的是,等号右边的字符串不要使用双引号(或单引号)包含,因为在双引号(或单引号)中的通配或正则不生效。
[root@localhost ~]# sys=RockyLinux #sys 变量赋值 [root@localhost ~]# [[ $sys == R* ]] #调用 sys 的值与 R*进行比较 [root@localhost ~]# echo $? 0 #判断成立
当想要判断某字符串的行首字符或行尾字符时,可以选择使用“=~”作为判断符号,因为在使用“=~”作为判断符号时可以进行正则匹配。
[root@localhost ~]# sys=RockyLinux [root@localhost ~]# [[ $sys =~ ^R ]] #匹配以 R 开头的字符串 [root@localhost ~]# echo $? 0 #判断成功 [root@localhost ~]# [[ $sys =~ x$ ]] #判断 sys 变量值是否以 x 为结尾 [root@localhost ~]# echo $? 0 #判断 sys 变量值是否以 x 为结尾
还可以同时判断字符串开头的字符:
[root@localhost ~]# [[ $sys =~ ^R.*$ ]] [root@localhost ~]# echo $? 0 #判断式中^R 表示判断 R 开头 #判断式中*表示出现在 R 和 x 之间的所有字符串 #判断式中x$表示判断 x 结尾