12.1 使用 if-then 语句
1、第一种if-then 语句
bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0 (该命令成功运行),位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。fi语句用来表示if-then语句到此结束。
if-then 语句格式:
if 命令 then 命令 fi |
例1:
[22:21:24 root@libin3 libin]# vim shell20 #!/bin/bash # echo this is if status if date then echo "I'm is libin" fi
[22:22:59 root@libin3 libin]# chmod u+x shell20
[22:23:06 root@libin3 libin]# ./shell20 2022年 08月 11日 星期四 22:23:11 CST I'm is libin |
例2:
[22:26:34 root@libin3 libin]# vim shell20 #!/bin/bash # echo this is if status if ping -c 1 www.baidu.com then echo ture fi
[22:26:44 root@libin3 libin]# ./shell20 PING www.a.shifen.com (183.232.231.174) 56(84) bytes of data. 64 bytes from 183.232.231.174: icmp_seq=1 ttl=128 time=30.2 ms --- www.a.shifen.com ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 30.217/30.217/30.217/0.000 ms ture |
例3:
如果 if语句后放入一个不能工作的命令,则状态码为非0,且bash shell 会跳过then后面的语句。
[22:43:53 root@libin3 libin]# vim shell21 /bin/bash #this is result error if libin then echo "this is error" fi if date then echo "this is success" fi echo "the are rhce"
[22:43:42 root@libin3 libin]# ./shell21 ./shell21:行3: libin: 未找到命令 this is rhcsa 2022年 08月 11日 星期四 22:43:44 CST this is success the are rhce |
1、第二种if-then 语句
在then部分,你可以使用不止一条命令。可以像在脚本中的其他地方一样在这里列出多条命令。bash shell会将这些命令当成一个块,如果if语句行的命令的退出状态值为0,所有的命令都会被执行;如果if语句行的命令的退出状态不为0,所有的命令都会被跳过。
格式:
if 命令;then 命令 fi |
例1:如果rhce=id,id为一个不存在的用户,则不会输出任何东西
[22:55:06 root@libin3 libin]# vim shell22 #!/bin/bash # the multiple command in the then-if rhce=student # if grep $rhce /etc/passwd;then echo "this is rhcsa" echo "this is rhce" echo "this is put in command echo:" ls -a /home/$rhce/.b* fi
[22:56:19 root@libin3 libin]# chmod u+x shell22 [23:00:12 root@libin3 libin]# ./shell22 student:x:1004:1004::/home/student:/bin/bash this is rhcsa this is rhce this is put in command echo: /home/student/.bash_history /home/student/.bash_logout /home/student/.bash_profile /home/student/.bashrc
写法2: #!/bin/bash # the multiple command in the then-if rhce=student # if grep $rhce /etc/passwd;then echo "this is rhcsa";echo "this is rhce";echo "this is put in command echo:";ls -a /home/$rhce/.b* fi |
12.2 if-then-else 语句
在if-then语句中,不管命令是否成功执行,你都只有一种选择。如果命令返回一个非零退出状态码,bash shell会继续执行脚本中的下一条命令。”if-then-else语句对比于if-then语句的区别就是:if后的命令错误,也会输出else后面的命令“。如果if后接错的交互式命令如data,最后会输出未找到命令。
格式:
if command then commands else commands fi |
例1:
[23:12:52 root@libin3 libin]# vim shell23 #!/bin/bash # the multiple command in the then-if rhce=nostudent # if grep $rhce /etc/passwd then echo "this is rhcsa" echo "this is rhce" echo "this is put in command echo:" ls -a /home/$rhce/.b* ; pwd else echo "the user $rhce does not exist on th /etc/passwd." fi
[23:17:27 root@libin3 libin]# chmod u+x shell23 [23:20:08 root@libin3 libin]# ./shell23 the user nostudent does not exist on th /etc/passwd. |
例2:if-then与if-then-else结合写法
[00:02:45 root@libin3 libin]# vim shell23-1 #!/bin/bash #the are if-then-else ststus # libin=data if $libin then echo "this is time" else echo "the in /etc/passwd users" fi
if date then echo "this is not's exist data" fi
[00:03:32 root@libin3 libin]# chmod u+x shell23-1 [00:02:27 root@libin3 libin]# ./shell23-1 ./shell23-1:行5: data: 未找到命令 the in /etc/passwd users 2022年 08月 12日 星期五 00:02:28 CST this is not's exist data |
12.3 嵌套 if
1、第一种嵌套if语句
需要检查脚本代码中的多种条件。对此,可以使用嵌套的if-then语句。
例1:检查查/etc/passwd文件中是否存在某个用户名以及该用户的目录是否存在,可以使用嵌套的if-then语句。嵌套的if-then语句位于主if-then-else语句的else代码块中。
写法1:我们发现else 后面只输出了if-then 并没有输出嵌套的if-then语句 内容 [00:06:45 root@libin3 libin]# vim shell24 #!/bin/bash # Test is if-then-else-fi V2 # libin=rhce # if grep $libin /etc/passwd then echo "the user $libin exist in system." else echo "the user $libin does exist in system." if ls -d /home/$libin/ then echo "howerver,$libin has a dir." fi fi
[00:07:29 root@libin3 libin]# chmod u+x shell24
[00:18:16 root@libin3 libin]# ./shell24 rhce:x:1006:1006:i am is libin,technology,10086,10086:/home/rhce:/bin/csh the user rhce exist in system.
注:我们发现在centos发行版系统里,如果最后两个fi,嵌套if好像没有生效 写法2:我们改变一下第一个fi的位置就可以输出嵌套的if-then语句内容,但是if-then-else 加 if-then 两种语句的结合。 [00:19:23 root@libin3 libin]# vim shell24 #!/bin/bash # Test is if-then-else-fi V2 # libin=rhce # if grep $libin /etc/passwd then echo "the user $libin exist in system." else echo "the user $libin does exist in system." fi if ls -d /home/$libin/ then echo "howerver,$libin has a dir." fi
[00:24:37 root@libin3 libin]# ./shell24 rhce:x:1006:1006:i am is libin,technology,10086,10086:/home/rhce:/bin/csh the user rhce exist in system. /home/rhce/ howerver,rhce has a dir.
写法3:我们将写法1的变量设置为一个不存在的变量再看变化 [00:28:59 root@libin3 libin]# vim shell24 #!/bin/bash # Test is if-then-else-fi V2 # libin=rhce-1 # if grep $libin /etc/passwd then echo "the user $libin exist in system." else echo "the user $libin does exist in system." if ls -d /home/$libin/ then echo "howerver,$libin has a dir." fi fi
[00:28:58 root@libin3 libin]# ./shell24 the user rhce-1 does exist in system. ls: 无法访问/home/rhce-1/: 没有那个文件或目录
写法4:我们将写法2的变量设置为一个不存在的变量再看变化 [00:29:25 root@libin3 libin]# vim shell24 #!/bin/bash # Test is if-then-else-fi V2 # libin=rhce-1 # if grep $libin /etc/passwd then echo "the user $libin exist in system." else echo "the user $libin does exist in system." fi if ls -d /home/$libin/ then echo "howerver,$libin has a dir." fi
[00:33:18 root@libin3 libin]# ./shell24 the user rhce-1 does exist in system. ls: 无法访问/home/rhce-1/: 没有那个文件或目录 |
注:从上面4种写法我们发现很难理清逻辑流程。所以不建议以上这种写法。其实综上表述可能有误,请看下面,这是一个探索的过程。
2、第二种嵌套if语句elif
格式:
If 命令 Then 命令 elif 命令 then more 命令 fi |
多种elif语句的if-then-elif嵌套结合
if command1 then command set 1 elif command2 then command set 2 elif command3 then command set 3 elif command4 then command set 4 fi |
elif语句行提供了另一个要测试的命令,如果elif后命令的退出状态码是0,则bash会执行第二个then语句部分的命令。
写法1:其实我们发现这种写法还是出现了上述的情况,但是上面是对if语句理解过于肤浅。 [01:08:08 root@libin3 libin]# vim shell25 #!/bin/bash # this is qian tao ifs- elif # libin=student # if grep $libin /etc/passwd then echo "the user $libin exist in the system." # elif ls -d /home/$libin then echo "the user $libin dones not exist in the system." echo "the user $libin exist in the system." # fi
[01:09:03 root@libin3 libin]# ./shell25 student:x:1004:1004::/home/student:/bin/bash the user student exist in the system.
写法2:我们创建一个用户,将该用户在/etc/passwd里面的信息删除,当看到这里的时候我们似乎看出了点特点,这就是嵌套if语句的特点:之前学到如果if语句行的命令的退出状态为非0,所有的命令都会被跳过,但是会输出else和elif后面的语句,这就相当于是否则判断语句;但if语句行如果为0时,则后面的语句也不会再执行(如第一种在else后面的语句及嵌套if和elif语句)这样我们理解就对了。
[01:13:09 root@libin3 libin]# useradd helloword [01:13:09 root@libin3 libin]# grep helloword /etc/passwd [01:15:31 root@libin3 libin]# vim shell25 #!/bin/bash # this is qian tao ifs- elif # libin=helloword # if grep $libin /etc/passwd then echo "the user $libin exist in the system /etc/passwd." # elif ls -d /home/$libin then echo "the user $libin dones not exist in the system." echo "the user $libin exist in the system." # fi
[01:15:56 root@libin3 libin]# chmod u+x shell25 [01:16:18 root@libin3 libin]# ./shell25 /home/helloword the user helloword dones not exist in the system. the user helloword exist in the system.
写法3:通过嵌套else语句,进一步让脚本检查拥有目录或者没有拥有目录的不存在用户。 我们为了实验将/home/helloword目录进行删除:我们发现有个局限性,就是嵌套if语句无法同时检测2个退出值都为0的条件。但是可以检测2个退出值都非0的条件;或者检测第一个退出值为非0,第2个退出值可以随意的结果。 (1)删除/etc/passwd ,没有删除/home/helloword目录前: [01:33:50 root@libin3 libin]# vim shell26 #!/bin/bash #this is ifs- elif and else libin=helloword if grep $libin /etc/passwd then echo "this user $libin is exist in the system" elif ls -d /home/$libin then echo "this user $libin does not exist in the system" echo "because,$libin has a dir" else echo "this user $libin does not exist in the system" echo "because,$libin not has a dir" fi
[01:52:03 root@libin3 libin]# chmod u+x shell26 [01:52:33 root@libin3 libin]# ./shell26 /home/helloword this user helloword does not exist in the system because,helloword has a dir (2)删除目录后: [02:07:12 root@libin3 libin]# rm -i /home/helloword/ [02:07:21 root@libin3 libin]# ./shell26 ls: 无法访问/home/helloword: 没有那个文件或目录 this user helloword does not exist in the system because,helloword not has a dir |
12.4 test 命令
test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得if-then语句不会再被执行。
1、test 命令的基本使用
test 命令格式:condition是test命令要测试的一系列参数和值。
test condition |
test命令用在 if-then语句中时的格式:
if test condition then commands fi |
例1:如果不写test命令的condition部分,它会以非0的退出状态码退出,并执行else语句块。
[19:50:20 root@libin3 libin]# vim shell27 #!/bin/bash #test commmand user # if test then echo "success" else echo "failed" fi
[19:53:10 root@libin3 libin]# chmod u+x shell27 [19:54:34 root@libin3 libin]# ./shell27 failed |
例子2:若加入一个条件时,test命令会测试该条件。可以使用test命令确定变量中是否有内容,这只需要一个简单的条件表达式。变量my_libin中包含内容(rhce)所以当test命令测试时,返回退出状态码为0,使得if then语句块中的语句得以执行。
[19:58:25 root@libin3 libin]# vim shell28 #!/bin/bash # test comand user 2 # my_libin="rhce" # if test $my_libin then echo "success" else echo "false" fi
[20:14:35 root@libin3 libin]# chmod u+x shell28 [20:14:44 root@libin3 libin]# ./shell28 success |
例子3:如果变量中没有包含内容,就会出现相反的结果。
[20:15:58 root@libin3 libin]# vim shell29 #!/bin/bash # test command user 3 # my_libin="" # if test $my_libin then echo "success" else echo "failed" fi
[20:26:14 root@libin3 libin]# chmod u+x shell29 [20:26:22 root@libin3 libin]# ./shell29 failed |
2、test 命令的拓展使用
无需在if-then语句中写test,基本格式;
if [ condition ] then commands fi
注:方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格, 否则就会报错。 |
test命令可以判断三类条件:
(1)数值比较
(2)字符串比较
(3)文件比较
12.4.1 数值比较
使用test命令最常见的情形是对两个数值进行比较。以下为测试两个值时可用条件参数。
1、常规对比
test命令的数值比较功能
比 较 |
描 述 |
n1 -eq n2 |
检查n1是否与n2相等 |
n1 -ge n2 |
检查n1是否大于或等于n2 |
n1 -gt n2 |
检查n1是否大于n2 |
n1 -le n2 |
检查n1是否小于或等于n2 |
n1 -lt n2 |
检查n1是否小于n2 |
n1 -ne n2 |
检查n1是否不等于n2 |
例1:数值条件测试可以用在数字和变量上。(可以变量与变量进行对比,也可以变量与数值对比 )
[20:41:06 root@libin3 libin]# vim shell30 #!/bin/bash # use v2 test compare # libin1=10 libin2=20 libin3=10 # if [ $libin1 -gt $libin2 ] then echo "true" else echo "false" fi
if [ $libin1 -eq $libin3 ] then echo "success" else echo "failed" fi
if [ $libin1 -eq 10 ] then echo "true" else echo "false" fi
[20:57:24 root@libin3 libin]# [20:57:24 root@libin3 libin]# chmod u+x shell30 [20:57:32 root@libin3 libin]# ./shell30 false success true |
2、浮点值测试
例1:涉及到浮点值时,数值会有限制,bash shell只能处理整数。echo没有问题,但是在基于数字的函数中就不行。
[21:03:17 root@libin3 libin]# vim shell31 #!/bin/bash #test using floating compare # libin1=6.66 echo "the test value is $libin1" # if [ $libin1 -gt 6 ] then echo "true" fi
[22:25:16 root@libin3 libin]# chmod u+x shell31 23:21:37 root@libin3 libin]# ./shell31 the test value is 6.66 ./shell31: 第 7 行:[: 6.66: 期待整数表达式 |
12.4.2 字符串比较
条件测试还允许比较字符串值。
字符串比较测试
比 较 |
描 述 |
str1 = str2 |
检查str1是否和str2相同 |
str1 != str2 |
检查str1是否和str2不同 |
str1 < str2 |
检查str1是否比str2小 |
str1 > str2 |
检查str1是否比str2大 |
-n str1 |
检查str1的长度是否非0 |
-z str1 |
检查str1的长度是否为0 |
1. 字符串相等性
例1:如果不相同就不会输出任何东西
[23:42:04 root@libin3 libin]# vim shell32 #!/bin/bash # test usring equality libin=root if [ $USER = $libin ] then echo "welcome $libin" fi
[23:40:36 root@libin3 libin]# ./shell32 welcome root |
例2:字符串不等条件也可以判断两个字符串是否有相同的值。在比较字符串的相等性时,比较测试会将所有的标点和大小写情况都考虑在内。
[23:46:38 root@libin3 libin]# cp shell32 shell33 [23:47:44 root@libin3 libin]# vim shell33 #!/bin/bash # test usring equality libin=rhce if [ $USER != $libin ] then echo "The not is $libin" else echo "The is $libin" fi
[23:49:31 root@libin3 libin]# ./shell33 The not is rhce |
2. 字符串顺序
(1)大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名;
(2)大于和小于顺序和sort命令所采用的不同。
例1:脚本中使用大于号,没有报错,但结果错误,脚本把大于号解释成了输出重定向,创建了一个rhce的文件。因为重定向完成了,test命令的返回值就是0,if语句就会认为执行成功。
解决这个问题,就需要正确转义大于号。
示例1: [12:19:37 root@libin3 libin]# vim shell34 #!/bin/bash #character string usring comparing # libin1=rhcsa libin2=rhce # if [ $libin1 > $libin2 ] then echo "$libin1 is greater than $libin2" else echo "$libin1 is less than $libin2" fi
[12:19:37 root@libin3 libin]# chmod u+x shell34 [12:19:04 root@libin3 libin]# ./shell34 rhcsa is greater than rhce
[12:19:07 root@libin3 libin]# ls -l rhce -rw-r--r-- 1 root root 0 8月 15 12:19 rhce
示例2:使用了转义,这里我们可能无法理解rhcsa大于rhce [12:20:34 root@libin3 libin]# cp shell34 shell35 [13:05:22 root@libin3 libin]# vim shell35 #!/bin/bash #character string usring comparing # libin1=rhcsa libin2=rhce # if [ $libin1 \> $libin2 ] then echo "$libin1 is greater than $libin2" else echo "$libin1 is less than $libin2" fi
[13:08:42 root@libin3 libin]# ./shell35 rhcsa is greater than rhce
示例3:把libin1、libin2变量定义为数值 13:08:43 root@libin3 libin]# cp shell35 shell36 [13:12:44 root@libin3 libin]# vim shell36 #!/bin/bash #character string usring comparing # libin1=10 libin2=20 # if [ $libin1 \> $libin2 ] then echo "$libin1 is greater than $libin2" else echo "$libin1 is less than $libin2" fi
[13:13:07 root@libin3 libin]# ./shell36 10 is less than 20
示例4:验证是否大写小于小写字母 [13:17:05 root@libin3 libin]# cp shell36 shell37 [13:18:01 root@libin3 libin]# vim shell37 #!/bin/bash #character string usring comparing # libin1=Rhcsa libin2=rhce # if [ $libin1 \> $libin2 ] then echo "$libin1 is greater than $libin2" else echo "$libin1 is less than $libin2" fi
[13:18:14 root@libin3 libin]# ./shell37 Rhcsa is less than rhce |
注:在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的
字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术
不同造成的。
比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort
命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺
序中小写字母出现在大写字母前。
3. 字符串大小
-n(是否长度非0)和-z(是否长度为0)可以检查一个变量是否含有数据。
例1:注,我这里没有定义libin3,所以它的字符串长度仍然为0,则退出状态码也为0,则就会输出if-then后面的语句,else的语句就跳过了。
[13:22:49 root@libin3 libin]# vim shell38 #!/bin/bash #testing string length comparing libin1=rhcsa libin2='' # if [ -n $libin1 ] then echo "The $libin1 does not empty" else echo "The $libin1 is empty" fi # if [ -z $libin2 ] then echo "The $libin2 is empty" else echo "The $libin2 does not empty" fi # if [ -z $libin3 ] then echo "The $libin3 does not empty" else echo "The $libin3 is empty" fi
[13:25:59 root@libin3 libin]# chmod u+x shell38 [13:26:11 root@libin3 libin]# ./shell38 e rhcsa does not empty The is empty The does not empty |
注:空的和未初始化的变量会对shell脚本测试造成灾难性的影响。如果不是很确定一个变量的
内容,最好在将其用于数值或字符串比较之前先通过-n或-z来测试一下变量是否含有值。
12.4.3 文件比较
文件比较测试很有可能是shell编程中最为强大、也是用得最多的比较形式。它允许你测试Linux文件系统上文件和目录的状态。
test命令的文件比较功能
比 较 |
描 述 |
-d file |
检查file是否存在并是一个目录 |
-e file |
检查file是否存在 |
-f file |
检查file是否存在并是一个文件 |
-r file |
检查file是否存在并可读 |
-s file |
检查file是否存在并非空 |
-w file |
检查file是否存在并可写 |
-x file |
检查file是否存在并可执行 |
-O file |
检查file是否存在并属当前用户所有 |
-G file |
检查file是否存在并且默认组与当前用户相同 |
file1 -nt file2 |
检查file1是否比file2新 |
file1 -ot file2 |
检查file1是否比file2旧 |
1. 检查目录-d
-d测试会检查指定的目录是否存在于系统中。
例1:这里使用 -d 测试条件检查dir变量中的目录是否存在,存在就会执行if-then语句的命令,若不存在就会输出else的内容。
示例1: [13:39:56 root@libin3 libin]# vim shell39 #!/bin/bash #file compare testing # dir=/home/student if [ -d $dir ] then echo "The $dir dir is exist" cd $dir ls else echo "The $dir dir is does not exist" fi
[14:10:22 root@libin3 libin]# chmod u+x shell39 [14:10:32 root@libin3 libin]# ./shell39 The /home/student dir is exist centos-release-7-9.2009.0.el7.centos.x86_64.rpm openssh-8.8p1-1.s12.rpms.bundle.sp3(1).tar openssh-8.8p1.tar.gz |
2. 检查对象是否存在-e
-e比较允许你的脚本代码在使用文件或目录前先检查它们是否存在。
例1:第一次检查用-e比较来判断用户是否有$HOME目录。如果有,接下来的-e比较会检查
libin文件是否存在于$HOME目录中。如果不存在,shell脚本就会提示该文件不存在,不需要进行更新。为确保更新操作能够正常进行,我们创建了libin文件,然后重新运行这个shell脚本。这一次在进行条件测试时,$HOME和libin文件都存在,因此当前日期和时间就被追加到了文件中。
[14:38:51 root@libin3 libin]# vim shell40 #!/bin/bash # check other a dir or file exists # local=$HOME file_name="libin" # if [ -e $local ] then #dir does exist echo "true,the $local dir" echo "now checking on the file,$file_name." # if [ -e $local/$file_name ] then #file does exist echo "true,on the filename" echo "update current date..." date >> $local/$file_name # else #file does not exist echo "file is not exist" echo "nothing to update" fi else #dir not exist echo "the $local dir does not exist" echo "nothing to update" fi
[14:47:18 root@libin3 libin]# chmod u+x shell40 [14:48:18 root@libin3 libin]# ./shell40 true,the /root dir now checking on the file,libin. file is not exist nothing to update
[14:54:23 root@libin3 libin]# cd /root/ [14:55:20 root@libin3 ~]# touch libin [14:55:33 root@libin3 ~]# cd /libin/libin [14:55:55 root@libin3 libin]# ./shell40 true,the /root dir now checking on the file,libin. true,on the filename update current date... |
3. 检查文件-f
-e比较可用于文件和目录。要确定指定对象为文件,必须用-f比较。
例1:先使用-e比较测试$HOME是否存在。如果存在,继续用-f来测试它是不是一个文件。如果它不是文件,就会输出一条信息。
[00:02:55 root@libin3 libin]# vim shell41 #!/bin/bash # check other a dir or file exists # libin_name=$HOME echo "the checking: $libin_name" # if [ -e $libin_name ] then #the does exist echo "The $libin_name does exist." echo "but is a file?" # if [ -f $libin_name ] then #the is a file echo "yes,$libin_name is a file." # else #libin_name the does not a file echo "no,$libin_name not does is a file" fi # else #libin_name does not exist echo "the $libin_name does not exist." echo "nothing to update" fi
[00:00:41 root@libin3 libin]# chmod u+x shell41 [00:07:36 root@libin3 libin]# ./shell41 the checking: /root The /root does exist. but is a file? no,/root not does is a file |
例2:对变量libin_name进行修改,将目录$HOME替换成$HOME/libin,看会有什么变化
对$HOME/libin进行的-f测试所返回的退出状态码为0,then语句得以执行,然后输出消息:
[00:26:20 root@libin3 ~]# ll /root/libin -rw-r--r-- 1 root root 43 8月 15 14:56 /root/libin
[00:27:40 root@libin3 libin]# cp shell41 shell42 [00:26:42 root@libin3 ~]# vim shell42 #!/bin/bash # check other a dir or file exists # libin_name=$HOME/libin echo "the checking: $libin_name" # if [ -e $libin_name ] then #the does exist echo "The $libin_name does exist." echo "but is a file?" # if [ -f $libin_name ] then #the is a file echo "yes,$libin_name is a file."
else #libin_name the does not a file echo "no,$libin_name not does is a file" fi
else #libin_name does not exist echo "the $libin_name does not exist." echo "nothing to update" fi
[00:28:12 root@libin3 libin]# ./shell42 the checking: /root/libin The /root/libin does exist. but is a file? yes,/root/libin is a file. |
4. 检查是否可读-r
在尝试从文件中读取数据之前,最好先测试一下文件是否可读。可以使用-r比较测试。
示例1: [01:27:08 root@libin3 libin]# ll /etc/rhce ls: 无法访问/etc/rhce: 没有那个文件或目录
[00:58:08 root@libin3 libin]# vim shell43 #!/bin/bash #test a file reading # libin=/etc/rhce # if [ -f $libin ] then #file exist # if [ -r $libin ] then #yes reading $libin tail -n1 $libin # else echo "false,the is a not exit $libin " fi else echo "false,the $libin is not reading" fi
[01:02:47 root@libin3 libin]# chmod u+x shell43 [00:59:01 root@libin3 libin]# ./shell43 false,the /etc/rhce is not reading
示例2: [01:23:10 root@libin3 libin]# echo "111" > /etc/rhce [01:25:04 root@libin3 libin]# ./shell43 111 |
5. 检查空文件-s
-s比较来检查文件是否为空,尤其是在不想删除非空文件的时候。要留心的是,当-s比较成功时,说明文件中有数据。
例1:-f比较测试首先测试文件是否存在。若存在,由-s比较来判断该文件是否为空。空文件会被删除。可以从ls –l的输出中看出sentinel并不是空文件,因此脚本并不会删除它。
[21:35:40 root@libin3 libin]# echo "wlcome to study redhat">> /root/rhce [21:36:09 root@libin3 libin]# cat /root/rhce wlcome to study redhat
[21:38:19 root@libin3 libin]# vim shell44 #!/bin/bash # test in a file empty # libin_name=$HOME/rhce # if [ -f $libin_name ] then if [ -s $libin_name ] then echo "the $libin_name exist" echo "not remove file" else echo "the $libin_name exists and empty" echo "delete empty file..." rm $libin_name fi else echo "file,$libin_name,not exist" fi [21:42:06 root@libin3 libin]# chmod u+x shell44 [21:42:12 root@libin3 libin]# ./shell44 the /root/rhce exist not remove file |
6.检查是否可写-w
-w比较会判断你对文件是否有可写权限。不单检查libin_name是否存在、是否为文件,还会检查该文件是否有写入权限。
例1:变量libin_name被设置成$HOME/rhce,该文件允许用户进行写入,我是root,因此当脚本运行时,-w测试表达式会返回非零退出状态,然后执行then代码块,将时间戳写入文件rhce中。
[22:26:32 root@libin3 libin]# vim shell45 #!/bin/bash #check file is writable # libin_name=$HOME/rhce echo "checking: $libin_name" echo "yes, $libin_name." echo "writable?" # if [ -w $libin_name ] then #is writable echo "writing time to $libin_name" date +%Y%H%M >> $libin_name # else #no writable echo "no writing time to $libin_name" fi
[22:11:29 root@libin3 libin]# chmod u+x shell45 [22:27:12 root@libin3 libin]# ./shell45 checking: /root/rhce yes, /root/rhce. writable? writing time to /root/rhce
[22:28:42 root@libin3 libin]# cat /root/rhce wlcome to study redhat 20222227 |
7. 检查文件是否可以执行-x
-x比较是判断特定文件是否有执行权限的一个简单方法。虽然可能大多数命令用不到它,但如果你要在shell脚本中运行大量脚本,它就能发挥作用。
例1:用-x比较来测试是否有权限执行shell46脚本。如果有权限,它会运行这个脚本。在首次成功运行test16.sh脚本后,更改文件的权限。
[22:55:14 root@libin3 libin]# vim shell46 #!/bin/bash # test file executa # if [ -x shell45 ] then echo "run the script" ./shell45 else echo "no run the script" fi
[22:54:21 root@libin3 libin]# chmod u+x shell46
[22:56:41 root@libin3 libin]# ./shell46 run the script checking: /root/rhce yes, /root/rhce. writable? writing time to /root/rhce
[22:54:02 root@libin3 libin]# chmod u-x shell45 [22:55:04 root@libin3 libin]# ./shell46 no run the script |
8. 检查所属关系-O
-O比较可以测试出你是否是文件的属主。
例1:脚本用-O比较来测试运行该脚本的用户是否是/etc/passwd文件的属主。若我用普通用户去执行脚本,就会测试失败。
#!/bin/bash # check file owner # if [ -O /etc/passwd ] then echo "true,the owner /etc/passwd file" else echo "false,are not owner /etc/passwd file" fi
[23:07:26 root@libin3 libin]# chmod u+x shell47 [23:07:31 root@libin3 libin]# ./shell47 true,the owner /etc/passwd file
[student@libin3 libin]$ PATH=$PATH:/libin/libin/ [student@libin3 libin]$ echo $PATH /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/student/.local/bin:/home/student/bin:/libin/libin/ [student@libin3 libin]$ sudo chmod o+x shell47 [student@libin3 libin]$ ./shell47 false,are not owner /etc/passwd file |
9. 检查默认属组关系-G
-G比较会检查文件的默认组,如果它匹配了用户的默认组,则测试成功。由于-G比较只会检查默认组而非用户所属的所有组。
例1:第一次执行脚本时,$HOME/test文件属于student组,所以就比较失败,因为-G只会比较默认组。
[23:26:18 root@libin3 libin]# ll /home/student/test -rw-rw-r-- 1 student student 11 8月 17 23:26 /home/student/test
[23:28:03 root@libin3 libin]# vim shell48 #!/bin/bash #check file group test # if [ -G $HOME/test ] then echo "is same group the file" else echo "not is group the file" fi
23:30:14 root@libin3 libin]# ./shell48 not is group the file
[23:30:18 root@libin3 libin]# su - student [student@libin3 libin]$ sudo chmod o+x shell48 [student@libin3 ~]$ cd /libin/libin [student@libin3 libin]$ ./shell48 is same group the file |
10. 检查文件日期-nt,-ot
在编写软件安装脚本时非常有用。有时候,你不会愿意安装一个比系统上已有文件还要旧的文件。
-nt比较会判定一个文件是否比另一个文件新。如果文件较新,那意味着它的文件创建日
期更近。-ot比较会判定一个文件是否比另一个文件旧。如果文件较旧,意味着它的创建日期
更早。
[23:39:35 root@libin3 libin]# vim shell49 #!/bin/bash #test file date if [ shell47 -nt shell46 ] then echo "shell47 new,shell46 old" else echo "shell46 new,shell47 old" fi # if [ shell45 -ot shell48 ] then echo "shell45 old,shell48 new" else echo "0" fi
[23:42:06 root@libin3 libin]# chmod u+x shell49 [23:49:13 root@libin3 libin]# ./shell49 shell47 new,shell46 old shell45 old,shell48 new |
12.5 复合条件测试
if-then语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
(1)[ condition1 ] && [ condition2 ]
(2)[ condition1 ] || [ condition2 ]
第1种布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。
第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为TRUE,then部分的命
令就会执行。
例1:AND布尔运算符的使用(两个条件都满足的情况下)
[21:52:23 root@libin3 libin]# ll $HOME/rhce ---------- 1 root root 68 8月 18 21:31 /root/rhce [21:40:33 root@libin3 libin]# vim shell50 #!/bin/bash # test AND compare # if [ -d $HOME ] && [ -w $HOME/rhce ] then echo "the file exist and write" else echo "the file not write" fi
[21:40:41 root@libin3 libin]# chmod u+x shell50 [21:40:49 root@libin3 libin]# ./shell50 the file exist and write |
例2:(2个条件满足1个即可)
示例1:(一个条件满足的情况下) [21:48:06 root@libin3 libin]# ll $HOME/rhcsa ls: 无法访问/root/rhcsa: 没有那个文件或目录 [21:42:57 root@libin3 libin]# vim shell51 #!/bin/bash # if-then || usering # if [ -d $HOME/rhcsa ] || [ -w $HOME/rhce ] then echo "true" else echo "false" fi
[21:46:47 root@libin3 libin]# chmod u+x shell51 [21:46:56 root@libin3 libin]# ./shell51 true
示例2:(二个条件都不满足的情况下) [21:50:46 root@libin3 libin]# ll $HOME/rhca ls: 无法访问/root/rha: 没有那个文件或目录 [21:50:52 root@libin3 libin]# vim shell51 #!/bin/bash # if-then || usering # if [ -d $HOME/rhcsa ] || [ -w $HOME/rhca ] then echo "true" else echo "false" fi
[21:51:20 root@libin3 libin]# ./shell51 false |
12.6 if-then 的高级特性
(1)用于数学表达式的双括号
(2)用于高级字符串处理功能的双方括号
12.6.1 使用双括号
双括号命令的格式:(( expression ))
expression可以是任意的数学赋值或比较表达式。除了test命令使用的标准数学运算符。
双括号命令符号
符 号 |
描 述 |
val++ |
后增 |
val-- |
后减 |
++val |
先增 |
--val |
先减 |
! |
逻辑求反 |
~ |
位求反 |
** |
幂运算 |
<< |
左位移 |
>> |
右位移 |
& |
位布尔和 |
| |
位布尔或 |
&& |
逻辑和 |
|| |
逻辑或 |
例1:(()) 的使用
[22:11:30 root@libin3 libin]# vim shell52 #!/bin/bash #using (()) # libin=12 if (( $libin ** 2 > 100 )) then (( libin2 = $libin ** 2 )) echo "the squaring is $libin is $libin2" fi
[22:12:28 root@libin3 libin]# ./shell52 the squaring is 12 is 144 |
例子2:
[22:19:03 root@libin3 libin]# vim shell53 #!/bin/bash #using (()) # libin1=10 libin2=20 libin3=30 # if (( $libin1 > $libin2 )) || (( $libin2 < $libin3 )) then echo "true" else echo "false" fi
[22:18:50 root@libin3 libin]# chmod +x shell53 [22:19:41 root@libin3 libin]# ./shell53 true |
12.6.2 使用双方括号
双方括号命令提供了针对字符串比较的高级特性。它提供了test命令未提供的另一个特性:模式匹配(pattern matching)。
双方括号命令的格式:[[ expression ]]
例1:这里使用了双等号(==),双等号将右边的字符串(r*)看作为一个模式,并且应用模式匹配规则。echo $USER 为root ,(r*)看它是否为字母r开头,如果是则退出状态为0。
示例1: [22:34:18 root@libin3 libin]# vim shell54 #!/bin/bash # using pattern matching # if [[ $USER == r* ]] then echo "true,echo $USER" else echo "false" fi [22:34:18 root@libin3 libin]# chmod u+x shell54 [22:33:32 root@libin3 libin]# ./shell54 true,echo root 示例2: [22:40:56 root@libin3 libin]# echo $HOSTNAME libin3.com [22:41:03 root@libin3 libin]# vim shell54 #!/bin/bash # using pattern matching # if [[ $HOSTNAME == r* ]] then echo "true,echo $HOSTNAME" else echo "false" fi
[22:41:42 root@libin3 libin]# ./shell54 false |