一、文件测试

文件测试大多都是单目测试,其用法相对简单,其格式为:

操作符:文件路径

可以用来测试的选项有:

-f:测试其是否为普通文件,即使用ls -l命令查看时,文件类型显示为 - 的文件;

-d:测试其是否为目录文件,即使用ls -l命令查看时,文件类型显示为 d的文件;

-e:测试文件是否存在,不论是目录还是文件,如果存在则为真,否则为假;

-r:测试文件对当前访问者来说(非创建者)是否可读;

-w:测试文件对当前访问者来说(非创建者)是否可写;

-x:测试文件对当前访问者来说(非创建者)是否可执行;

-s:测试文件是否有大小,如果有大小则为真,否则为假;

-l:测试文件是否为链接文件

 

例如要检验/tmp/test10是否不存在,如果不存在就创建之:

[root@localhost~]# vim if_exist.sh

#!/bin/bash
#
if [ ! -e /tmp/test10 ]; then
#测试文件不存在,故对文件存在的情况取反
        mkdir /tmp/test10
fi

[root@localhost~]# bash -x if_exist.sh

+ '[' '!' -e /tmp/test10 ']'
+ mkdir /tmp/test10

[root@localhost~]# ls /tmp

a.sh  d.sh keyring-bgxXAq  orbit-gdm           pulse-yCmeAwocSW1U   virtual-root.plTHoO  yum.log
b.sh  e.sh keyring-Xi9NCS  orbit-root          test10               virtual-root.q9Sgpu
c.sh  f.sh keyring-xva5ss pulse-uP5T8Y6V6nIN virtual-root.nBhtJw virtual-root.rQ0Eab
#test10这个目录已经创建了。

 

二、短路操作符

上面测试 /tmp/test10是否存在的例子,其实可以写作更简单的形式:[-e /tmp/test10 ] || mkdir /tmp/test10

这里的 || 就是短路操作符,意为或运算,即先测试|| 前面的语句,如果为真,就不测试 || 后面的语句了;如果|| 前面的语句为假,则继续测试 || 后面的语句。

短路操作符主要有以下几种:

&&: 与运算, 与运算的情况有:

&& =

&& =

&& =     

&& =

 ||: 或运算,或运算的情况有:

|| =

|| =

|| =

|| =

注意,与运算具有优先级,即与运算先操作,或运算后操作

 

如果某个用户不存在,就创建该用户的例子,也可以用这种方式写:

id $UserName&> /dev/null || useradd $UserName

 

现在把这个例子复杂化:使用与运算和或运算的形式,测试一个用户是否存在,如果存在就显示其以存在,否则就创建这个用户

[root@localhosttutor]# vim if_user6.sh

#1/bin/bash
 
UserName=$1
! id $UserName&> /dev/null && useradd $UserName || echo "$UserNameexists."
#如果用户存在,则 && 前的部分为假,那么需要判断&& 后面的部分;
#如果用户不存在,则 &&前面的部分为真,那么不需要判断&& 后面的部分
#对于 || 运算来说,如果用户不存在,则前半部分都为假,则需要运行 || 后面的部分


[root@localhosttutor]# bash -x if_user6.sh root

+UserName=root
+ id root
+ echo 'rootexists.'
root exists.

[root@localhosttutor]# bash -x if_user6.sh roott

+ UserName=roott
+ id roott
+ useraddroott

 

三、文件测试及短路运算综合实例

1. 给定一个路径,判断如果为普通文件,显示之;如果为目录,显示之;否则显示为无法识别

 

[root@localhost tutor]# vim if_file.sh

#!/bin/bash
#
 
if [ ! -e $1]; then
        echo "No such file."
        exit 7
fi
# 先判断文件是否存在
if [ -f $1 ];then
        echo "Common file."
elif [ -d $1]; then
        echo "Directory."
else
        echo "Unknown file."
fi

 

[root@localhost tutor]# bash if_file.sh /tmp

Directory.

[root@localhost tutor]# bash if_file.sh /etc

Directory.

[root@localhost tutor]# bash if_file.sh /etc/fstab

Common file.

[root@localhost tutor]# bash if_file.sh /etc/fstabb

No such file.

[root@localhost tutor]# bash if_file.sh /dev/sda

Unknown file.

 

2. 写一个脚本,判断/var/log目录中所有文件的类型

[root@localhost tutor]# vim file_type.sh

#!/bin/bash
#
 
for File in/var/log/*; do
        if [ -f $File ]; then
                echo "$File: Commonfile."
        elif [ -d $File ]; then
                echo "$File:Directory."
        else
                echo "$File: Unknownfile."
        fi
done

[root@localhost tutor]# bash file_type.sh

/var/log/anaconda.yum.log:Common file.
/var/log/audit:Directory.
/var/log/boot.log:Common file.
/var/log/ConsoleKit:Directory.

 

3. 写一个脚本:可以接受一个参数,其使用形式如下:

          script.sh {start|stop|restart|status}

如果参数为start,创建空文件/var/lock/subsys/script,并显示“Starting scriptsuccessfully.”;

如果参数为stop,则删除文件/var/lock/subsys/script,并显示“Stop script finished.”;

如果参数为restart,则删除文件/var/lock/subsys/script后重新创建,并显示“Restarting scriptsuccessfully.”;

如果参数为status,那么:

          如果/var/lock/subsys/script文件存在,则显示为“script is running.

          否则,则显示为“script is stopped.

其它任何参数:则显示“script.sh{start|stop|restart|status}

 

这里稍微补充一下,$0为脚本自身的名称,但是引用$0时,会引用全路径及名称,故如果只想引用脚本本身的名称,可以使用basename $0

[root@localhost tutor]# vim service.sh

——————————————以下为脚本内容——————————————————

#!/bin/bash
#
 
SvcName=`basename$0`
 # 使用basename取该脚本的基名
LockFile="/var/lock/subsys/$SvcName"
 # 提供一个锁文件的路径
 
if [ $# -lt 1]; then
# 判断参数个数是否少于1,是则给用户提示信息,并退出脚本
        echo "Usage: $SvcName {start |stop | restart | status}"
        exit 3
fi
 
if [ $1 =='start' ]; then
 
        if [ -e $LockFile ]; then
# 先判断该文件是否存在,如果存在,则不创建
                echo "$SvcName isrunning."
        else
                touch $LockFile &>/dev/null
# 如果参数为start,且文件不存在,则创建该文件
                echo "Starting $SvcNamesuccessfully."
        fi
             
elif [ $1 =='stop' ]; then
 
        if [ -e $LockFile ]; then
# 如果传递的参数是stop,则先判断文件是否存在,如果存在就删除该文件
                rm -f $LockFile &>/dev/null
                echo "Stopping $SvcNamefinished."
        else
# 如果文件不存在,则无需删除,给出提示信息即可
                echo "$SvcName is stoppedyet."
        fi
       
elif [ $1 =='restart' ]; then
        rm -f $LockFile &> /dev/null
        touch $LockFile &> /dev/null
# 如果参数为restart,则先删除该文件,再创建之
        echo "Restarting $SvcNamesuccessfully."
elif [ $1 =='status' ]; then
# 如果参数为status,那么需要用到嵌套语句,考虑文件是否存在
        if [ -e $LockFile ]; then
                echo "$SvcName isrunning."
        else
                echo "$SvcName isstopped."
        fi
else
        echo "Usage: $SvcName {start |stop | restart | status}"
        exit 4
# 如果输入的参数不是这4个中的一个,给用户提示信息,并退出,且错误编号与无参数的情况不同
fi

 

——————————————下面来测试该脚本——————————————————

 

[root@localhost tutor]# chmod +x service.sh

[root@localhost tutor]# ./service.sh

Usage:service.sh {start | stop | restart | status}

[root@localhost tutor]# echo $?

3

[root@localhost tutor]# ./service.sh start

Starting service.sh successfully.

[root@localhost tutor]# ls /var/lock/subsys

abrt-ccpp  atd    blk-availability  cups       local         network         pcscd    rpc.statd  sshd
abrtd      auditd certmonger        haldaemon  lvm2-monitor NetworkManager  postfix  rsyslog
acpid      autofs crond             ip6tables  messagebus   openct          rpcbind  service.sh
# 可以看到/var/lock/subsys下成功创建了service.sh文件


[root@localhost tutor]# ./service.sh stop

Stopping service.sh finished.

[root@localhost tutor]# ls /var/lock/subsys

abrt-ccpp  atd    blk-availability  cups       local         network         pcscd    rpc.statd
abrtd      auditd certmonger        haldaemon  lvm2-monitor NetworkManager  postfix  rsyslog
acpid      autofs crond             ip6tables  messagebus   openct          rpcbind  sshd
# 传递的参数为stop,则强行删除了 service.sh文件


[root@localhost tutor]# ./service.sh restart

Restarting service.sh successfully.

[root@localhost tutor]# ls /var/lock/subsys

abrt-ccpp  atd    blk-availability  cups       local         network         pcscd    rpc.statd  sshd
abrtd      auditd certmonger        haldaemon  lvm2-monitor NetworkManager  postfix  rsyslog
acpid      autofs crond             ip6tables messagebus    openct          rpcbind  service.sh
# 传递的参数为restart,强行删除了 service.sh文件后又创建了一遍


[root@localhost tutor]# ./service.sh status

service.sh isrunning.
# 传递的参数为status,则显示当前文件存在与否


[root@localhost tutor]# ./service.sh stop

Stopping service.shfinished.

[root@localhost tutor]# ./service.sh status

service.sh isstopped.

[root@localhost tutor]# ./service.sh stat

Usage:service.sh {start | stop | restart | status}
# 传递错误参数,给予提示信息后退出


[root@localhost tutor]# ./service.sh start

Startingservice.sh successfully.

[root@localhost tutor]# ./service.sh start

service.sh isrunning.
# 文件已经存在了


[root@localhost tutor]# ./service.sh stop

Stoppingservice.sh finished.

[root@localhost tutor]# ./service.sh stop

service.sh isstopped yet.
# 文件不存在


上述脚本是红帽系统遵循SysV风格启动服务时的常用启动格式