## 使用 test 命令(数值比较、字符串比较、文件比较) 在前边的 if 语句中,if 根据后面命令的退出码是否为 0 来决定是否执行 then 后面的语句 块,如果存在 else 语句,在命令退出码非 0 的情况下才会执行 else 后面的语句块。 并且if 后面跟着的都是命令。那么脚本中的 if 语句能不能像其他语言,如 Java 中的 if 语句根 据后面的表达式返回的 true 或 false 来决定是否执行 then 或 else 后面的语句块呢! 但是要注意,在脚本中 if 判断的一定是后面命令的退出码是 0 或非 0,那么解决的方法是什 么呢!就是 `test 命令`,**test 命令提供了在 if…then 语句中测试不同条件的途径,如果 test 后面的条件成立,那么 test 命令返回的退出码为 0,如果条件不成立,test 命令返回的退 出码为 1**,这样既满足了 if 语句根据命令退出码来决定执行方向,同时又拓宽了判断条 件。 * test 命令一般有两种格式: * `test 表达式` * `[ 表达式 ]` * 但是需要注意的是如果使用方括号方式时,要注意在表达式** 两边加上空格 **,否则执行会提示错误信息。 * 使用第一种方式的语句格式如下。 if test 表达式 then 语句块 fi * 当 test 命令后面的的表达式成立,test 命令的退出码为 0,如果 test 命令后面的表达式不成立,test 命令的退出码为 1。如下面的例子。 * 例子:判断两个数值类的大小并输出信息 #!/bin/bash # 声明变量并赋值 var1=100 var2=200 # 判断变量 var1 是否大于变量 var2 if test $var1 -gt $var2 then echo "$var1 > $var2" else echo "$var1 < $var2" fi * 控制台显示: 100 < 200 * 上面的脚本中使用了 test 命令,后面跟着的是逻辑表达式。**还有一种方式可以替代上面的方式,就是使用方括号来替代 test 命令**,修改上面的代码如下。 * 例子:使用方括号的方式实现上面的例子,通常这种方式使用较为普遍。 #!/bin/bash var1=100 var2=200 if [ $var1 -gt $var2 ] then echo "$var1 > $var2" else echo "$var1 < $var2" fi * 注意方括号是 test 命令的简写方式,方括号中是 test 命令的条件,另外需要注意的是方括号的两边要有空格,否则会报错。通常使用的就是这种方式。 * test 命令可以判断三类条件: * 1、数值比较 * 2、字符串比较 * 3、文件比较 ### 一、数值比较 数值比较比较常见,下面的表中列出了数值比较符,这和 Java 中是有区别的。 * 数值比较:
比较符 说明
v1 -eq v2 v1 是否等于 v2
v1 -gt v2 v1 是否大于 v2
v1 -ge v2 v1 是否大于或等于 v2
v1 -lt v2 v1 是否小于 v2
v1 -le v2 v1 是否小于或等于 v2
v1 -ne v2 v1 是否不等于 v2
* 例子:比较大小。通过一个例子说明数值比较。 #!/bin/bash var1=200 var2=300 # 判断 var1 是否等于 var2 if [ $var1 -eq $var2 ] then echo "$var1 等于$var2" # 判断 var1 是否大于 var2 elif [ $var1 -gt $var2 ] then echo "$var1 大于$var2" # 判断 var1 是否小于 var2 elif [ $var1 -lt $var2 ] then echo "$var1 小于$var2" fi * 控制台输出: 200 小于 300 * 例子:比较小数是否可以??浮点数是否可以比较!通过例子说明: #!/bin/bash var1=3.33 var2=3 if [ $var1 -gt $var2 ] then echo "$var1 大于$var2" else echo "$var1 小于等于$var2" fi * 控制台输出: 3.33 小于等于 3 比较结果是错误的,**注意:脚本中只能处理整数,不支持浮点数作为数值比较**。 ### 二、字符串比较 test 命令还支持比较字符串,**比较字符串和比较数值使用的比较符是不同的**,**使用标准的数学比较符进行字符串的比较, 而用文本代码来比较数值**,这是要注意的。 * 字符串比较符列表说明:
比较符 说明
s1 = s2 s1 是否于 s2 相同
s1 != s2 s1 是否于 s2 不同
s1 > s2 s1 是否比 s2 大
s1 < s2 s1 是否比 s2 小
-n s1 s1 的长度是否不等于 0,是否非空
-z s1 s1 的长度是否为 0,是否为空
* 例子:当前用户是否是 root(**比较字符串是否相同**。) #!/bin/bash # 判断当前登录用户是否是 root if [ $USER = "root" ] then echo "当前用户是超级管理员:$USER" # 判断当前登录用户是否是 yarn elif [ $USER = "hadoop01" ] then echo "当前用户是:$USER" fi * 控制台显示: 当前用户是:hadoop01 * 判断字符串不相同,使用方式和判断字符串相同相似,可以使用在相同的场合。 * 例子:判断用户 #!/bin/bash user=yarn if [ $user != "root" ] then echo "你不是管理员 root" elif [ $user = "root" ] then echo "欢迎管理员$user 登录!" fi * 控制台显示: 你不是管理员 root * 例子:比较字符串是否相等(**字符串比较考虑字符的大小写**) #!/bin/bash if [ "Hello" = "hello" ] then echo "Hello = hello" else echo "Hello != hello" fi * 控制台显示: Hello != hello #### 比较字符串大小时要注意,大于号和小于号要转义,否则系统会将大于号和小于号认为是重定向符,字符串当成文件名。如下例子。 * 例子:字符串大于小于比较时,大于号和小于号要转义,否则结果出错 #!/bin/bash # 注意:系统会将大于号>认为是重定向符,认为 bcd 是文件名 # 会在当前目录创建一个 bcd 文件 if [ "abc" > "bcd" ] then echo "abc > bcd" else echo "abc <= bcd" fi * 控制台输出: abc > bcd * 脚本似乎正确执行,事实上系统将大于号视同重定向符,将 bcd 认为是文件名,会在当 前目录创建一个 bcd 文件,并且执行结果也是错的。要注意,字符串比较时的大于号和 小于号要转义,修改上面脚本如下。 * 例子:修改上面的例子 #!/bin/bash # 大于号要转义 if [ "abc" \> "bcd" ] then echo "abc > bcd" else echo "abc <= bcd" fi * 控制台显示: abc <= bcd * **判断字符串变量是否 非空使用比较符-n,判断字符串是否为空使用比较符-z**。在字符串操作中使用较多,下面通过例子说明。 * 例子:字符串非空判断 #!/bin/bash # 声明变量 var1="abcdefg" # 声明一个空串 var2="" var3= # 判断变量非空 if [ -n "$var1" ] then echo "变量 var1 非空:$var1" fi # 判断变量是否为空取反,判断变量是否不为空 if [ ! -z "$var1" ] then echo "变量 var1 非空:$var1" fi # 判断变量是否为空 if [ -z "$var2" ] then echo "变量 var2 为空" fi # 判断变量是否不为空取反,判断变量是否为空 if [ ! -n "$var2" ] then echo "变量 var2 为空" fi # 判断变量是否为空 if [ -z "$var3" ] then echo "变量 var3 为空" fi # 变量 var4 未定义,变量任然为空 if [ -z "$var4" ] then echo "变量 var4 为空" fi * 控制台输出: 变量 var1 非空:abcdefg 变量 var1 非空:abcdefg 变量 var2 为空 变量 var2 为空 变量 var3 为空 变量 var4 为空 ### 三、文件比较 * 脚本中常用到的是文件比较,test 命令允许测试 Linux 系统上的文件和目录的状态。下面表中是文件比较常用到的测试函数。
测试符 说明
-d filename filename 是否存在并是一个目录
-e filename filename 是否存在
-f filename filename 是否存在并是一个文件
-r filename filename 是否存在并可读
-s filename filename 是否存在并非空
-w filename filename 是否存在并可写
-x filename filename 是否存在并可执行
-O filename filename 是否存在并属于当前用户
-G filename filename 是否存在并且默认组与当前用户相同
**这些测试函数可以让你检查文件系统中的文件。在脚本中对要访问的文件进行操作前要做的检查工作,脚本中经常要用到**。 * 例子:判断文件是否为目录:-d 检查文件是否在文件系统中以目录的方式存在,当要在此目录下读写文件时经常用到,如果目录本身不存在,要给出提示信息或首先创建目录,下面通过例子说明。 #!/bin/bash # 声明一个目录变量 dir1=/home/hadoop01/bash01 # 判断/home/hadoop01/bash01 是否存在并且是个目录 if [ -d "$dir1" ] then # 切换到/home/hadoop01/bash01 目录下 cd ${dir1} # 创建一个临时目录 tmp mkdir tmp # 切换到 tmp 目录下 cd tmp # 创建一个空日志文件 touch logs.log # 将当天的日期输入到文件中 date > logs.log # 在控制台显示日志文件内容 cat logs.log else # 如果目录不存在,在控制台显示提示信息 echo "$dir1 is not exist!" fi 脚本执行后,如果/home/hadoop01/bash01 目录存在,会在目录下创建一个 tmp 目录,在 tmp目录中创建一个 logs.log 日志文件,如果目录不存在,会在控制台显示提示信息:目录不存在。 * 下面的例子首先判断当前用户是否是 hadoop01,如果不是 hadoop01 用户不允许操作 hadoop01 用户的 工作目录。如果当前用户是 hadoop01,判断/home/hadoop01/bash01/tmp 目录是否存在,如果存在 追加 hadoop01 用户登录信息到日志文件中。如果 tmp 目录不存在,首先创建 tmp 目录并且在 目录中创建日志文件并输入用户登录信息。 #!/bin/bash if [ $USER = "hadoop01" ] then if [ -d "/home/hadoop01/bash01/tmp" ] then cd /home/hadoop01/bash01/tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" >> logs.log else cd /home/hadoop01/bash01 mkdir tmp cd tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" > logs.log fi else echo "You is not User hadoop01!" fi * 日志文件信息格式: 02/29/16 17:40:49: User hadoop01 login system * 例子:使用-e 判断文件是否存在,文件可以是目录和普通文件: -e 判断文件或目录是否存在,判断更宽泛,包括普通文件和目录文件。下面通过例子说明。 #!/bin/bash # 判断/home/hadoop01/bash01 目录是否存在 if [ -e "/home/${USER}/bash01" ] then # 判断 tmp 目录是否存在 if [ -e "/home/${USER}/bash01/tmp" ] then # 判断 tmp 目录下的 logs.log 日志文件是否存在 if [ -e "/home/${USER}/bash01/tmp/logs.log" ] then cd /home/${USER}/bash01/tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" >> logs.log else cd /home/${USER}/bash01/tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" > logs.log fi else mkdir /home/${USER}/bash01/tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" > /home/${USER}/bash01/tmp/logs.log fi else echo "/home/${USER}/bash01 is not exist!" fi 在脚本中首先判断目录是否存在,然后判断目录下的日志文件是否存在,如果文件存在 追加日志信息到日志文件,否则创建一个日志文件。脚本中对 tmp 目录也做了判断,如 果不存在,创建 tmp 目录和 logs.log 文件。 * -e 判断文件或者目录是否存在,如果具体到目录,可以使用-d。如果具体到文件,可以 使用-f。下面通过例子说明。 #!/bin/bash # 判断目录是否存在,包括 bash01/tmp if [ -d "/home/hadoop01/bash01/tmp" ] then # 判断 logs.log 日志文件是否存在 if [ -f "/home/hadoop01/bash01/tmp/logs.log" ] then cd /home/hadoop01/bash01/tmp dateStr=`date +%D" "%T` # 追加日志信息 echo "$dateStr: User $USER login system" >> logs.log else cd /home/hadoop01/bash01/tmp dateStr=`date +%D" "%T` # 创建日志文件并输入日志信息 echo "$dateStr: User $USER login system" > logs.log fi else # 递归创建目录 mkdir -p /home/hadoop01/bash01/tmp cd /home/hadoop01/bash01/tmp dateStr=`date +%D" "%T` echo "$dateStr: User $USER login system" > logs.log fi * -r 用来判断对文件是否有可读权限,如下说明: --w-rw-r--. 1 hadoop01 hadoop01 35 3 月 1 10:49 file04 * 文件 file04 的属主是 hadoop01,但是 hadoop01 没有读权限只有写权限,如果要查看文件内容会提示警告信息,如下: $ cat file04 cat: file04: 权限不够 * 下面的例子是判断文件是否有读写权限如果有显示文件内容,如果没有读权限,先修改用户权限,然后显示文件内容。 #!/bin/bash # 声明变量 file=/home/hadoop01/bash01/file04 # 判断文件是否可以读 if [ -r "$file" ] then # 显示文件内容 cat $file else # 判断当前用户是否是 hadoop01 if [ "$USER" = "hadoop01" ] then # 给 hadoop01 用户增加读权限 chmod u+r $file cat $file else # 如果不是 hadoop01 用户,提示信息 echo "You are not a hadoop01 user!" fi fi * -s 用来判断文件是否不为空。如果要将空文件删除,首先要判断文件是否为空,对于非空的文件删除要谨慎。下面通过一个例子说明。 * 想创建一个空文件: touch newfile ls -l -rw-rw-r--. 1 hadoop01 hadoop01 0 3 月 1 11:11 newfile * 判断 newfile 文件是否为空。 #!/bin/bash file=/home/hadoop01/bash01/newfile # 判断文件是否不为空 if [ -s "$file" ] then echo "$file is a non empty file" else echo "$file is an empty file" fi # 向文件中追加内容 echo "We are learning Bash Shell!" >> $file # 判断文件是否不为空 if [ -s "$file" ] then echo "$file is a non empty file" echo "The contents fo the file:" # 显示文件尾部的内容 tail $file else echo "$file is an empty file" fi * -w 用来判断当前用户对文件是否有写权限,下面通过例子说明。 #!/bin/bash # 判断当前用户是否是 hadoop01 if [ "$USER" = "hadoop01" ] then cd $HOME/bash01 # 创建一个新的空文件 touch logfile # 去掉 yarn 用户的文件写权限 chmod u-w logfile # 判断当前用户 yarn 对 logfile 文件是否有写权限 if [ -w "logfile" ] then # 这段代码不会执行,因为用户没有写权限 echo "You have write permission!" echo "Not executed!" else echo "You do not have permission to write!" fi # 为 yarn 用户增加对 logfile 文件的写权限 chmod u+w logfile if [ -w "logfile" ] then # 这段代码会执行 echo "You already have permission to write!" echo "You have permission to write!" >> logfile else echo "You do not have permission to write!" echo "Not executed!" fi else # 如果不是 hadoop01 用户没有操作权限 echo "You do not have permission!" fi * -x 用来判断用户对文件是否有执行权限,通常的使用场景是在脚本中需要执行其他的脚本,要判断用户对脚本是否有执行权限,如果用户拥有脚本的执行权限则执行脚本,否则提示信息或修改脚本的执行权限。下面通过例子说明。 * 首先创建一个测试执行脚本 bash31_1.sh 并去掉 hadoop01 用户的执行权限: #!/bin/bash echo "Bash Shell script action!" * bash31.sh: #!/bin/bash file=/home/yarn/bash01/bash31_1.sh # 取消文件属主的执行权限 chmod u-x $file if [ "$USER" = "yarn" ] then # 判断文件是否有执行权限 if [ -x "$file" ] then echo "Not executed!" else # 增加用户的执行权限 chmod u+x $file # 执行脚本 $file fi else echo "You do not have premission!" fi * -O 用来判断当前用户是否是文件的属主。 * 首先使用 root 用户的权限创建一个文件 rootfile,然后使用 hadoop01 用户创建一个 yarnfile 文件: -rw-r--r--. 1 root root 15 3 月 1 12:50 rootfile -rw-rw-r--. 1 yarn hadoop01 15 3 月 1 12:55 yarnfile * 下面通过脚本说明-O 的使用方法。 #!/bin/bash yarnfile=/home/hadoop01/bash01/hadoop01file rootfile=/home/hadoop01/bash01/rootfile if [ "$USER" = "hadoop01" ] then # 判断文件 hadoop01file 的属主是否是当前用户 if [ -O "$hadoop01file" ] then # 会执行 echo "$hadoop01file is owner user hadoop01!" else echo "Not executed!" fi # 判断 rootfile 文件的属主是否是当前用户 if [ -O "$rootfile" ] then echo "Not executed!" else # 会执行 echo "$rootfile is not owner user hadoop01!" fi else echo "You do not have permission!" fi * -G 用来判断文件的默认组是否与当前用户的组相同,使用较少,下面通过例子说明。 #!/bin/bash yarnfile=/home/hadoop01/bash01/hadoop01file rootfile=/home/hadoop01/bash01/rootfile if [ "$USER" = "hadoop01" ] then # 判断文件的默认组是否和当前用户是同一个组 if [ -G "$hadoop01file" ] then # 会执行 echo "With the user hadoop01 with a group! " else echo "Not executed!" fi # 判断文件的默认组是否和当前用户是同一个组 if [ -G "$rootfile" ] then echo "Not executed!" else # 会执行 echo "With is not the user hadoop01 with a group!" fi else echo "You do not have permission!" fi