如何在Bash中检查一个文件或目录是否存在?
很多时候,在编写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
不使用IF语句的等效变体。
[ -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存在并且是可执行的,则为真。
总结
在本指南中,我们向你展示了如何在Bash中检查一个文件或目录是否存在的方法。
如果你有任何问题或反馈意见,请随时留言。