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

当您在编写 Shell 脚本时,您很多时候可能会发现自己需要根据文件是否存在来执行某些操作。

在 Bash 中,您可以使用 test 命令检查文件是否存在并确定文件的类型。

test 命令采用以下语法形式之一:

test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]

如果您希望脚本可移植,则应该使用 test 命令的旧语法形式 [,因为这种形式在所有 POSIX shell 上都可用的。test 命令的新语法版本 [[ (双括号) 被大多数使用 Bash , Zsh 和 Ksh 作为默认 shell 的现代系统支持。

检查文件是否存在

检查文件是否存在时,最常用的文件运算符是 -e-f 。第一个将检查文件是否存在而不管类型如何,而第二个将仅在文件是常规文件 (不是目录或设备)时返回 true

检查文件时最好的一个方法是将 test 命令与 if 语句结合使用。下面的任何片段都是检查 /etc/resolv.conf 文件是否存在:

FILE=/etc/resolv.conf
if test -f "$FILE"; then
echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [[ -f "$FILE" ]]; then
echo "$FILE exist"
fi

如果要根据文件是否存在执行不同的操作,只需使用 if/else 结构:

FILE=/etc/resolv.conf

if [ -f "$FILE" ]; then
echo "$FILE exist"
else
echo "$FILE does not exist"
fi

在处理名称中包含空格的文件时,请始终使用双引号以避免出现问题。

您也可以使用不带 if 语句的 test 命令。只有在 test 命令的退出状态为真时才执行操作符 && 后的命令,

test -f /etc/resolv.conf && echo "$FILE exist"
[ -f /etc/resolv.conf ] && echo "$FILE exist"
[[ -f /etc/resolv.conf ] && echo "$FILE exist"

如果要在 && 运算符后运行一系列命令,简单地将所有命令括在大括号中并用 ;&& 分隔的:

[ -f /etc/resolv.conf ] && { echo "$FILE exist"; cp "$FILE" /tmp/; }

&& 相反,操作符 || 后的语句只有在 test 命令的退出状态为 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"

您也可以使用双括号 [[ 而不是单个括号 [

检查文件是否不存在

与许多其他语言类似, test 表达式可以使用 ! (感叹号)作为逻辑非运算符:

FILE=/etc/docker
if [ ! -f "$FILE" ]; then
echo "$FILE exist and it is a directory"
fi

与上述相同:

[ ! -f /etc/docker ] || echo "$FILE does not exist"

检查多个文件是否存在

您可以使用 -a (或 &&)测试是否存在多个文件,而不是使用复杂的嵌套 if/else 结构:

FILE=/etc/docker
if [ -f /etc/resolv.conf -a -f /etc/hosts ]; then
echo "$FILE is a directory"
fi
FILE=/etc/docker
if [ -f /etc/resolv.conf && -f /etc/hosts ]; then
echo "$FILE is a directory"
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"

test 命令的运算符

test 命令包括以下 文件 运算符,允许您测试特定类型的文件:

  • -b FILE - 如果文件存在且为块特殊文件,则为 True 。
  • -c FILE - 如果文件存在且为特殊字符文件,则为 True 。
  • -d FILE - 如果文件存在且为目录,则为 True 。
  • -e FILE - 如果文件存在且为文件,则为 True ,不管文件类型 (节点,目录,套接字等)。
  • -f FILE - 如果文件存在且为常规文件 (不是目录或设备),则为 True 。
  • -G FILE - 如果文件存在且与运行命令的用户具有相同的组,则为 True 。
  • -h FILE - 如果文件存在且为符号链接,则为 True 。
  • -g FILE - 如果文件存在且设置了 set-group-id (sgid) 标志,则为 True。
  • -k FILE - 如果文件存在且设置了粘滞位标志,则为 True。
  • -L FILE - 如果文件存在且为符号链接,则为 True。
  • -O FILE - 如果文件存在并且由运行该命令的用户拥有,则为 True。
  • -p FILE - 如果文件存在且为管道,则为 True。
  • -r FILE - 如果文件存在且可读,则为 True。
  • -S FILE - 如果文件存在且为套接字,则为 True。
  • -s FILE - 如果文件存在且非零大小,则为 True。
  • -u FILE - 如果文件存在并 set-user-id (suid) 标志,则为 True。
  • -w FILE - 如果文件存在且可写,则为 True。
  • -x FILE - 如果文件存在且可执行,则为 True。

结论

在本教程中,我们向您展示了如何使用 Bash 检查文件或目录是否存在。