文件/目录判断
[ -a FILE ] 如果 FILE 存在则为真。
[ -b FILE ] 如果 FILE 存在且是一个块文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字符文件则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 指定的文件或目录存在时为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且设置了SGID则为真。
[ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了冒险位则为真。
[ -p FILE ] 如果 FILE 存并且是命令管道时为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小非0时为真则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID位时为真。
[ -w FILE ] 如果 FILE 存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真(目录为真)。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且默认组为当前组则为真。(只检查系统默认组)
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在且从上次读取之后已经做过修改则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
字符串判断
[ -z STRING ] 如果STRING的长度为0则为真,即空是真
[ -n STRING ] 如果STRING的长度非0则为真,即非空是真
[ STRING1 ] 如果字符串不为空则为真,与-n类似
[ STRING1 == STRING2 ] 如果两个字符串相同则为真
[ STRING1 != STRING2 ] 如果字符串不相同则为真
[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则为真。
[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则为真。
数值判断
[ INT1 -eq INT2 ] INT1和INT2两数相等为真 ,=
[ INT1 -ne INT2 ] INT1和INT2两数不等为真 ,<>
[ INT1 -gt INT2 ] INT1大于INT2为真 ,>
[ INT1 -ge INT2 ] INT1大于等于INT2为真,>=
[ INT1 -lt INT2 ] INT1小于INT2为真 ,<
[ INT1 -le INT2 ] INT1小于等于INT2为真,<=
逻辑判断
[ ! EXPR ] 逻辑非,如果 EXPR 是false则为真。
[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 和 EXPR2 全真则为真,同[ ] || [ ]
[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或 EXPR2 为真则为真,同[ ] && [ ]
括号的作用
单方括号[ ] 条件测试,即test
双圆括号(( )) 数学表达式,括号中将被运算,大于号(>)、小于号(<)不必转义
双方括号[[ ]] 高级字符串处理函数,可使用正则表达式
示例1:
[ $a != 1 || $b = 2 ] ==>错误
[[ $a != 1 || $b = 2 ]] ==>等价于[ $a != 1 ] || [ $b = 2 ]
[ "$a" -lt "$b" ] ==>等价于(("$a" < "$b"))
示例2:下面四个判断是一样的
(( a > b )) && (( a < c ))
[[ "$a" > "$b" ]] && [[ "$a" < "$c" ]]
[ "$a" \> "$b" ] && [ "$a" \< "$c" ]
[ $a -gt $b -a $a -lt $c ]
说明事项
1、[ ]表示条件测试。注意这里的空格很重要。要注意在'['后面和']'前面都必须要有空格
2、在shell中,then和fi是分开的语句。如果要在同一行里面输入,则需要用分号将他们隔开。
3、注意if判断中对于变量的处理,需要加 双引号,以避免一些不必要的错误。没有加双引号会在一些含空格等的字符串变量判断的时候产生错误。比如[ -n "$var" ]如果var为空会出错
4、判断是不支持浮点值的
5、如果只单独使用>或者<号,系统会认为是输出或者输入重定向,并且不会提示错误,因此要对这些符号进行转意
6、在默认中,运行if语句中的命令所产生的错误信息仍然出现在脚本的输出结果中,若不希望出现,需将错误重定向至/dev/null
7、使用-z或者-n来检查长度的时候,没有定义的变量也为0
8、空变量和没有初始化的变量可能会对shell脚本测试产生灾难性的影响,因此在不确定变量的内容的时候,在测试号前使用-n或者-z测试一下
9、? 变量包含了之前执行命令的退出状态(最近完成的前台进程),0表示执行正确
案例与技巧
- 简写
if [ expr ]; then command; fi 可简写为 [ expr ] && command;
if [ ! expr ]; then command; fi 可简写为 [ expr ] || command; - 字符串包含
[[ $str =~ expr ]] #利用字符串 =~ 正则式判断,$str为被查找的字串,expr为匹配的字串
[[ $A == *$B* ]] #利用通配符
[[ ${A/${B}//} == $A ]] #利用字符串替换
[ `cmd|grep expr` !="" ] #利用grep有匹配不为空判断,下同
[ -n "$(cmd|grep expr)" ] #直接看匹配结果是否为空,注意结果必须转为双引号内的变量
[ `cmd|grep expr -c` -gt 0 ] #利用grep -c计数与0比较,有匹配结果>0 - 判断文件中是否包含字符串$str
- 利用$?
grep "$str" /path/file > /dev/null
[ $? -eq 0 ] && echo '包含' - 利用-c计数
[ `grep -c "$str" /path/file` -gt 0 ] && echo '包含'
- 利用$?
- 进程是否存在
[ -n "$(pidof 进程名)" ] #直接看匹配结果是否为空,注意结果必须转为双引号内的变量
[ `pidof 进程名|wc -l` -gt 0] #利用wc -l计数与0比较,有匹配结果>0
如果进程是由其它进程打开的子进程,那么pidof也许取不到号,此时用ps即可
ps -ef|grep -w 进程名|grep -v grep
注意:需要grep -w完全匹配,并且用grep -v去除grep本身 - 判断主机是否可以上网
ping -c 1 114.114.114.114 > /dev/null 2>&1
if [ $? -eq 0 ];then
echo 检测网络正常
else
echo 检测网络连接异常
fi