很多时候,在编写Shell脚本时,你可能会发现自己处于这样一种情况:你需要根据一个文件的存在与否来执行一个动作。
在Bash中,你可以使用test命令来检查一个文件是否存在,并确定该文件的类型。
测试命令采用以下语法形式之一:
test EXPRESSION [ EXPRESSION ] [[ EXPRESSION ]]
如果你希望你的脚本是可移植的,你应该倾向于使用旧的测试[命令,它在所有的POSIX shell上都可用。新的升级版测试命令[[(双括号)在大多数使用Bash、Zsh和Ksh作为默认shell的现代系统中都支持。
检查文件是否存在
当检查一个文件是否存在时,最常用的 FILE 操作符是 -e 和 -f 。第一个运算符将检查一个文件是否存在,而第二个运算符只在 FILE 是一个普通的文件(不是一个目录或设备)时返回真。
在检查一个文件是否存在时,最可读的选择是使用 test 命令与 if 语句相结合。
下面的三段代码片段都可以检查 /etc/resolv.conf 文件是否存在。
FILE=/etc/resolv.conf if test -f "$FILE"; then echo "$FILE exists." fi
FILE=/etc/resolv.conf if [ -f "$FILE" ]; then echo "$FILE exists." fi
FILE=/etc/resolv.conf if [[ -f "$FILE" ]]; then echo "$FILE exists." fi
如果你想根据文件是否存在来执行不同的操作,只需使用 if/then 结构即可。
FILE=/etc/resolv.conf if [ -f "$FILE" ]; then echo "$FILE exists." else echo "$FILE does not exist." fi
注意:始终使用双引号,以避免在处理文件名中含有空格时出现问题。
你也可以使用没有 if 语句的 test 命令。只有当测试命令的 exit status 为真时,&& 操作符后的命令才会被执行。
test -f /etc/resolv.conf && echo "$FILE exists." [ -f /etc/resolv.conf ] && echo "$FILE exists." [[ -f /etc/resolv.conf ]] && echo "$FILE exists."
如果你想在 && 运算符之后运行一系列的命令,只需将这些命令用大括号括起来,用 ; 或 && 隔开,例如:
[ -f /etc/resolv.conf ] && { echo "$FILE exist."; cp "$FILE" /tmp/; }
与 && 相反,只有当测试命令的退出状态为 false 时,|| 操作符后的语句才会被执行,例如:
[ -f /etc/resolv.conf ] && echo "$FILE exist." || echo "$FILE does not exist."
检查目录是否存在
操作符 -d 允许你测试一个文件是否是一个目录。
例如,要检查 /etc/docker 目录是否存在,你将使用:
FILE=/etc/docker if [ -d "$FILE" ]; then echo "$FILE is a directory." fi
或者
[ -d /etc/docker ] && echo "$FILE is a directory."
你也可以使用双括号[[,而不是单括号[。
检查文件是否不存在
与许多其他语言类似,测试表达式可以使用!(感叹号)逻辑非运算符进行否定,例如:
FILE=/etc/docker if [ ! -f "$FILE" ]; then echo "$FILE does not exist." fi
或者:
[ ! -f /etc/docker ] && echo "$FILE does not exist."
检查是否有多个文件存在
你可以使用 -a(或 && 与 [[ )来测试是否存在多个文件,而不是使用复杂的嵌套的 if/else 结构。
if [ -f /etc/resolv.conf -a -f /etc/hosts ]; then echo "Both files exist." fi
或者
if [[ -f /etc/resolv.conf && -f /etc/hosts ]]; then echo "Both files exist." fi
或者
[ -f /etc/resolv.conf -a -f /etc/hosts ] && echo "Both files exist."
或者
[[ -f /etc/resolv.conf && -f /etc/hosts ]] && echo "Both files exist."
文件测试操作符
测试命令包括以下FILE操作符,允许你测试特定类型的文件。
-b FILE - 如果FILE存在,并且是一个特殊的块状文件,则为真。
-c FILE - 如果FILE存在,并且是一个特殊字符的文件,则为真。
-d FILE - 如果FILE存在并且是一个目录,则为 "真"。
-e FILE - 如果FILE存在并且是一个文件,则为真,无论其类型如何(节点、目录、套接字等)。
-f FILE - 如果FILE存在并且是一个普通的文件(而不是一个目录或设备),则为真。
-G FILE - 如果FILE存在,并且与运行命令的用户有相同的组,则为真。
-h FILE - 如果FILE存在,并且是一个符号链接,则为真。
-g FILE - 如果FILE存在并且设置了set-group-id(sgid)标志,则为真。
-k FILE - 如果FILE存在并且有一个粘性位标志被设置,则为真。
-L FILE - 如果FILE存在,并且是一个符号链接,则为真。
-O FILE - 如果FILE存在并且为运行命令的用户所拥有,则为 "true"。
-p FILE - 如果FILE存在,并且是一个管道,则为真。
-r FILE - 如果FILE存在并且可以被读取,则为真。
-S FILE - 如果FILE存在并且是一个套接字,则为 "真"。
-s FILE - 如果FILE存在并且大小不为零,则为真。
-u FILE - 如果FILE存在,并且设置了set-user-id(suid)标志,则为真。
-w FILE - 如果FILE存在并且是可写的,则为真。
-x FILE - 如果FILE存在并且是可执行的,则为真。