2017年已经开启,我们迎来了新的起点,公众号也将带来新的内容——linux相关主题。
作为通信行业的专业人士,我们不仅需要分析各种节点信令,还要掌握Linux的多种操作,包括系统操作、命令使用以及在Linux环境下进行简单的shell编程来处理日常任务(我们真是多才多艺啊)。
在编程中,我们经常使用if-else条件判断来根据设定的条件执行不同的命令。我在编写shell脚本时,总是记不清如何判断文件是否存在、字符串是否为空等问题。最近,我的朋友偶尔也会接触到简单的shell编程,并询问这些内容,每次都需要通过谷歌或百度查找后依然无法清晰掌握。
最近几天,我根据自己的使用经验整理了if条件判断中从-a到-z的所有参数,希望能为有此需求的朋友提供帮助。
1
if-else的格式
if条件判断的格式非常简单,但需要注意的是,shell中每个if语句之后必须有一个fi来结束,同时要注意空格(重要的事情说三遍),如下:
if [ 条件 ];then
符合该条件执行的语句
elif [ 条件 ];then
符合该条件执行的语句
else
符合该条件执行的语句
fi
2
文件的判断
文件的判断相对简单,主要是判断文件是否存在、有什么样的权限等,但涉及的参数却很多,因为文件有不同的类型:普通文件、目录(即文件夹,d)、字符设备文件(c)、块设备文件(b)、命名管道文件(p)、套接字文件(s)、符号链接文件(l)等。具体各个文件类型的功能在此不做过多说明,重点介绍if条件中针对文件的判断:
-a/-e 判断文件是否存在,存在则为真。这两个参数可以判断所有类型文件是否存在,目前还没发现有什么不同。用法:if [ -a FileName ] 或 if [ -e FileName ] 如下:
-b 查看块设备文件是否存在,存在则为真,块设备文件的标识为“b”。用法:if [ -b FileName ] 如下,/dev/sda为块文件;test由1可知为普通文件,所以即使存在通过-b判断依然为False:
-c 查看字符设备文件是否存在,存在则为真,字符设备文件标识为“c”。用法:if [ -c FileName ] 如/dev/tty为字符设备文件;test由1可知为普通文件,所以即使存在通过-c判断依然为False:
-d 查看目录即文件夹是否存在,存在则为真,目录文件类型标识为“d”。用法:if [ -d FileName ] 如test是普通文件,通过-d判断为False;dirtest则为目录/文件夹:
-f 查看普通文件是否存在,存在则为真,普通文件就是通过ls -l查看时没有任何标识的文件。用法:if [ -f FileName ] 如下,test为普通文件,ifelse为目录文件,/dev/tty由3可知为字符设备文件:
-u 用来查看文件是否存在并且设置了SUID位,存在并且设置了SUID位则为真。那么什么是SUID位呢?SUID即Set UID,当s这个标识出现在文件所有者的执行权限x上时,即说明此文件设置了SUID位,SUID的目的就是让本来没有相应权限的用户运行此程序的时候可以访问他没有权限访问的资源,非常好的一个例子就是/usr/bin/passwd这个程序:
[coreuser@HK-centos ifelse] ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 27832 Jun 10 2014 /usr/bin/passwd
[coreuser@HK-CentOS ifelse]
我们知道Linux中的用户密码存在/etc/shadow中,在最新的版本中shadow权限如下,所以此文件只有万能王root才可以写入:
[coreuser@HK-CentOS ifelse] ls -l /etc/shadow
———-. 1 root root 1412 Jan 5 19:01 /etc/shadow
[coreuser@HK-CentOS ifelse]
但是我们知道不仅仅root用户可以修改密码,其他用户也可以修改自己的密码,那么没有权限怎么写入到shadow文件中呢?这就是因为passwd这个程序中的SUID的作用,因为SUID的存在并且任何用户都有passwd的执行权限,所以当其他用户在执行passwd的时候就拥有了root的权限也就可以对shadow进行写入操作了。设置文件的SUID位可以通过chmod u+s FileName设置,取消则用chmod u-s FileName.回到-u参数,用法:if [ -u FileName ] 如下,通过chmod修改test文件的SUID并判断:
-g 用来查看文件是否存在并且设置了SGID位,存在并且设置了SGID位则为真。通过6我们知道SUID是Set UID,那么SGID就很简单了,SGID=Set GID,设置获取该文件所属用户组的权限。SGID通过chmod g+s FileName设置,取消则用chmod g-s FileName用法:if [ -g FileName ] 如下,通过chmod修改test的SGID并判断:
-h/-L 这两个参数都是判断符号链接文件是否存在,文件存在并且为符号链接文件则为真;-h在一些老系统上可能无效;符号链接文件的标识为“l”,即我们常说的软连接——相当于快捷方式。用法:if [ -h FileName ] 或 if [ -L FileName ] 如下:
-k 判断文件存在并且设置了SBIT即Sticky Bit粘滞位,存在并且设置SBIT为真。什么是SBIT呢?SBIT是针对其他用户设置的,更多的是应用在目录文件中,作用是目录下的文件只有root和拥有者才有权利删除,举个例子/tmp:
[coreuser@HK-CentOS ifelse] ls -l / | grep tmp
drwxrwxrwt. 27 root root 8192 Jan 6 23:49 tmp
[coreuser@HK-CentOS ifelse]
回到-k用法:if [ -k FileName ] 如下,通过chmod +t FileName或者chmod o+t FileName来设置文件的SBIT,使用chmod -t FileName或者chmod o-t FileName来取消之,并进行判断:
-p 判断一个命名管道(named pipe)文件是否存在,存在且是一个命名管道文件则为真,named pipe文件标识为“p”,可以使用mkfifo FileName来创建一个named pipe文件。用法if [ -p FileName ] 如下:
-r 判断一个文件是否存在并且当前用户是否拥有可读权限,文件存在且可读则为真。用法:if [ -r FileName] 如test文件的拥有者是coreuser,且权限为-rwxrwx—,即只有coreuser和所在用户组拥有可读可写可执行权限,其他用户不具有任何权限,那么当用不属于coreuser所在用户组的其他用户如om_admin来判断的时候为假,如下:
-w 跟-r类似,判断一个文件是否存在并且当前用户是否拥有可写权限,文件存在且可写则为真。用法:if [ -w FileName ] 依然以test为例,如下:
-x 同-w、-r类似,用来判断文件是否存在并且当前用户是否拥有可执行权限,文件存在且可执行则为真。用法:if [ -x FileName ] 继续以test文件为例,如下:
-s 此处为小s,判断文件是否存在且文件大小不为零即非空文件,存在且非空则为真。-s也是针对所有类型的文件包括目录、普通文件、块文件等等,但是对于目录永远都不会为空(可以思考一下为什么^_^)用法:if [ -s FileName ] 如下可以先通过du来判断文件是否为空,:
-O 判断文件存在且被当前有效用户ID所指定的用户所拥有时则为真,很拗口对不对?其实就是判定当前用户是否是文件的拥有者。用法:if [ -O FileName ] 如下:
-G 判断文件存在且被当前用户所在的有效用户组所拥有时则为真。用法:if [ -G FileName ] 如下:
-S 此处为大S,判断文件存在且为套接字(Socket)文件则为真,套接字(Socket)文件标识为“s”(木有找到如何定义一个套接字(Socket)文件/(ㄒoㄒ)/~~,希望知道的朋友可以指点一二)。用法:if [ -S FileName ] 如下,/dev/log为一个套接字(Socket)文件:
-N 判断文件存在且自上次读取之后曾修改过则为真,即判断文件是否被修改过。用法:if [ -N FileName ] 如下,test被修改之后判断为真,但是通过cat读取且不再修改之后判断则为假:
文件比较——什么?文件也有比较?诚然,文件的比较更多是判断谁更新鲜,一共有三个参数:
-nt 用法 if [ FileName1 -nt FileName2 ];如果FileName1比FileName2新即最新修改,或者FileName1存在且FileName2不存在,以上两种情况为真。
-ot 用法 if [ FileName1 -ot FileName2 ];如果FileName1比FileName2旧,或者FileName1不存在且FileName2存在,以上两种情况为真。如下:
-ef 用法 if [ FileName1 -ef FileName2 ];如果FileName1和FileName2都存在且引用到相同的设备和inode编号时则为真,如下以硬链接为例,一个文件和他的硬链接的inode相同;比较特殊的软连接,虽然inode编号不同,但是因为都指向通一个文件,所以依然为真,即快捷方式和源文件一样:
另外还有一个跟文件有关的参数-t,我们看以上各个参数都是判断文件,-t比较特殊是判断文件描述符(FD),但是对文件描述符知之甚少,所以不得其解,还望知道的朋友指点。
3
字符串的判断
字符串的判断相对比较容易,是否为空和两个字符串长度比较即可。
-z 判断字符串是否为空串即长度是否为0,空串则为真。用法:if [ -z String ] 如下:
-n 判断字符串是否为非空串即长度不为0,长度不为0则为真。用法:if [ -n String ] 直接对字符串判断也有同样效果,用法:if [ String ] 如下:
字符串比较:
!= 如果两个字符串不相等则为真。
==或者= 如果两个字符串相等则为真。如下:
除了文件和字符串的判断,if-else中还有支持数字的关系运算符:
用法: if [ int1 -eq/-ne/-gt/-ge/-lt/-le int2 ]
-eq 判断两个数是否相等,相等为真
-ne 判断两个数是否相等,不等于为真
-gt 判断左边的数是否大于右边的,是则为真
-ge 判断左边的数是否大于等于右边的,是则为真
-lt 判断左边的数是否小于右边的,是则为真
-le 判断左边的数小于等于右边的,是则为真