如何在Bash中检查一个文件或目录是否存在?

评论 0 浏览 0 2019-03-13

很多时候,在编写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中检查一个文件或目录是否存在的方法。

如果你有任何问题或反馈意见,请随时留言。

最后更新2023-06-28
0 个评论
标签