Section 22.1: 文件类型测试
-e 条件运算符测试文件是否存在(包括所有文件类型:目录等)。
if [[ -e $filename ]]; then
echo "$filename exists"
fi
还有针对特定文件类型的测试。
if [[ -f $filename ]]; then
echo "$filename is a regular file"
elif [[ -d $filename ]]; then
echo "$filename is a directory"
elif [[ -p $filename ]]; then
echo "$filename is a named pipe"
elif [[ -S $filename ]]; then
echo "$filename is a named socket"
elif [[ -b $filename ]]; then
echo "$filename is a block device"
elif [[ -c $filename ]]; then
echo "$filename is a character device"
fi
if [[ -L $filename ]]; then
echo "$filename is a symbolic link (to any file type)"
fi
对于符号链接,除了 -L 之外,以下这些测试也适用于返回 false 的失效链接。
if [[ -L $filename || -e $filename ]]; then
echo "$filename exists (but may be a broken symbolic link)"
fi
if [[ -L $filename && ! -e $filename ]]; then
echo "$filename is a broken symbolic link"
fi
Section 22.2: 字符串比较和匹配
字符串比较在带引号的字符串之间使用 == 运算符。!= 运算符否定比较。
if [[ "$string1" == "$string2" ]]; then
echo "\$string1 and \$string2 are identical"
fi
if [[ "$string1" != "$string2" ]]; then
echo "\$string1 and \$string2 are not identical"
fi
如果右侧未引用,则它是 $string1 匹配的通配符模式。
string='abc'
pattern1='a*'
pattern2='x*'
if [[ "$string" == $pattern1 ]]; then
# the test is true
echo "The string $string matches the pattern $pattern"
fi
if [[ "$string" != $pattern2 ]]; then
# the test is false
echo "The string $string does not match the pattern $pattern"
fi
'<' 和 '>' 运算符按字典顺序比较字符串(字符串没有小于或等于或大于或等于的运算符)。
空字符串的测试。
if [[ -n "$string" ]]; then
echo "$string is non-empty"
fi
if [[ -z "${string// }" ]]; then
echo "$string is empty or contains only spaces"
fi
if [[ -z "$string" ]]; then
echo "$string is empty"
fi
在上面,'-z' 检查可能意味着 '$string' 未设置,或者它被设置为空字符串。要区分 empty 和 unset,请使用:
if [[ -n "${string+x}" ]]; then
echo "$string is set, possibly to the empty string"
fi
if [[ -n "${string-x}" ]]; then
echo "$string is either unset or set to a non-empty string"
fi
if [[ -z "${string+x}" ]]; then
echo "$string is unset"
fi
if [[ -z "${string-x}" ]]; then
echo "$string is set to an empty string"
fi
其中 x 是任意的。或以表格形式显示:
+-------+-------+-----------+
$string is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [[ -z ${string} ]] | true | true | false |
| [[ -z ${string+x} ]] | true | false | false |
| [[ -z ${string-x} ]] | false | true | false |
| [[ -n ${string} ]] | false | false | true |
| [[ -n ${string+x} ]] | false | true | true |
| [[ -n ${string-x} ]] | true | false | true |
+-----------------------+-------+-------+-----------+
或者,可以在 case 语句中检查状态:
case ${var+x$var} in
(x) echo empty;;
("") echo unset;;
(x*[![:blank:]]*) echo non-blank;;
(*) echo blank
esac
其中 [:blank:] 是特定于语言环境的水平间距字符(制表符、空格等)。
Section 22.3: 测试命令的退出状态
退出状态 0:成功
退出状态非 0:失败
要测试一个命令的退出状态可以用下面的例子:
if command;then
echo 'success'
else
echo 'failure'
fi
Section 22.4: 单行测试
您可以执行以下操作:
[[ $s = 'something' ]] && echo 'matched' || echo "didn't match"
[[ $s == 'something' ]] && echo 'matched' || echo "didn't match"
[[ $s != 'something' ]] && echo "didn't match" || echo "matched"
[[ $s -eq 10 ]] && echo 'equal' || echo "not equal"
(( $s == 10 )) && echo 'equal' || echo 'not equal'
单行测试的返回状态:
command && echo 'exited with 0' || echo 'non 0 exit'
cmd && cmd1 && echo 'previous cmds were successful' || echo 'one of them failed'
cmd || cmd1 #If cmd fails try cmd1
Section 22.5: 文件比较
if [[ $file1 -ef $file2 ]]; then
echo "$file1 and $file2 are the same file"
fi
“同一文件” 意味着就地修改其中一个文件会影响另一个文件。两个文件可以是相同的,即使它们具有不同的名称,例如,如果它们是硬链接,或者它们是具有相同目标的符号链接,或者如果一个是指向另一个的符号链接。
如果两个文件的内容相同,但它们是不同的文件(因此修改一个文件不会影响另一个文件),那么 '-ef' 报告它们不同。如果要逐字节比较两个文件,请使用 cmp 实用程序。
if cmp -s -- "$file1" "$file2"; then
echo "$file1 and $file2 have identical contents"
else
echo "$file1 and $file2 differ"
fi
要生成文本文件之间差异的可读列表,请使用 diff 实用程序。
if diff -u "$file1" "$file2"; then
echo "$file1 and $file2 have identical contents"
else
: # the differences between the files have been listed
fi
Section 22.6: File access tests
if [[ -r $filename ]]; then
echo "$filename is a readable file"
fi
if [[ -w $filename ]]; then
echo "$filename is a writable file"
fi
if [[ -x $filename ]]; then
echo "$filename is an executable file"
fi
这些测试会考虑权限和所有权,以确定脚本(或从脚本启动的程序)是否可以访问该文件。
小心争用条件 (TOCTOU):仅仅因为测试现在成功并不意味着它在下一行仍然有效。通常最好尝试访问文件并处理错误,而不是先测试然后再处理错误,以防文件在此期间发生更改。
Section 22.7: 数值比较
数值比较使用 -eq 运算符会比较友好。
if [[ $num1 -eq $num2 ]]; then
echo "$num1 == $num2"
fi
if [[ $num1 -le $num2 ]]; then
echo "$num1 <= $num2"
fi
有六个数字运算符:
-
-eq等于 -
-ne不等于 -
-le小于等于 -
-lt小于 -
-ge大于等于 -
-gt大于
要记得的是,[[ ... ]] 中的 < 和 > 运算符比较的是字符串,而不是数字。
if [[ 9 -lt 10 ]]; then
echo "9 is before 10 in numeric order"
fi
if [[ 9 > 10 ]]; then
echo "9 is after 10 in lexicographic order"
fi
The two sides must be numbers written in decimal (or in octal with a leading zero). Alternatively, use the ((…)) arithmetic expression syntax, which performs integer calculations in a C/Java/…-like syntax.
两边必须是以十进制形式书写的数字(或前导为零的八进制形式)。或者,使用 ((...)) 算术表达式语法,该语法以类似 C/Java/...-的语法执行整数计算。
x=2
if ((2*x == 4)); then
echo "2 times 2 is 4"
fi
((x += 1))
echo "2 plus 1 is $x"