首页 > 编程笔记 > Linux笔记 阅读:13

Linux test命令的用法(非常详细)

test 命令是 Bash 中重要的判断命令,也是 shell 脚本中条件判断的重要辅助工具。当我们需要让程序自动判断哪些事情是成立的时,test 命令就派上用场了。

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 结尾

相关文章