Contents

检查Shell脚本中是否存在目录

1. 概述

在这个 shell 脚本教程中,我们将讨论如何检查指定目录是否已经存在。

首先,我们将介绍检查目录是否存在的基础知识。然后,我们将指出在编写 shell 脚本时可能出现的一些注意事项。

2. 检查Shell中是否存在目录

在本节中,我们将介绍检查目录是否存在的 POSIX 方法。

**在 Linux 上,大多数 shell 都提供了内置的文件测试操作符 ,我们可以使用这些操作符,而无需依赖外部工具。**当然,这些内置操作符是 POSIX 兼容的。因此,当我们使用这些运算符时,很容易移植我们的 shell 脚本。

2.1. -d文件测试运算符

** -d文件测试运算符检查指定目录是否存在。它评估为布尔值。**

让我们创建一个临时目录并查看*-d*测试运算符的实际作用:

DIR="$(mktemp -d)"
if [ -d "$DIR" ]; then
  echo "$DIR exists."
fi

相反,我们也可以测试目录是否不存在:

if [ ! -d "$DIR" ]; then
  echo "$DIR doesn't exist."
fi

正如我们所看到的,这非常简单,我们也可以进行短路评估:

$ [ -d "/tmp"] && echo "/tmp exists"
/tmp exists

请记住,我们应该始终将文件名或文件名变量括在双引号中,以防止出现意外行为。

在大多数情况下,这对于基本的 shell 脚本来说已经足够了。但是,我们可能需要注意一些警告。让我们也进入那个。

2.2. 处理指向目录的符号链接

有时,我们可能有指向目录的符号链接。例如,让我们创建一个指向*/tmp*目录的符号链接:

$ ls -s /tmp t

现在,这个符号链接不是一个常规的目录,所以我们不能对它执行常规的目录操作:

$ rmdir t
rmdir: failed to remove 't': Not a directory

出于这个原因,我们需要为目录提供额外的检查:

if [ -d "$DIR" ]; then
  if [ -L "$DIR" ]; then
    echo "$DIR is a symlink."
    # Treat $DIR as symlink
  else
    echo "$DIR is a regular directory."
    # Treat $DIR as directory
  fi
else
  echo "$DIR doesn't exist."
fi

** -L文件测试运算符检查指定的文件名是否是符号链接。**如果是这种情况,我们可以将此符号链接视为常规文件——例如,使用rm而不是rmdir

或者,我们可以通过在目录名称末尾添加正斜杠来避免对符号链接进行额外检查

if [ -d "${DIR}/" ]; then
  echo "$DIR is a regular directory."
else
  echo "$DIR doesn't exist."
fi

2.3. 解决目录和文件名冲突

有时,以下代码段中的代码会出现意外行为:

if [ ! -d "$DIR" ]; then
  # Directory doesn't exist
  mkdir "$DIR"
fi

由于以下两个原因之一,上述代码段中的测试将评估为false

  • $DIR不存在
  • $DIR存在,但它不是目录

出于这个原因,我们可以进行另一个额外的检查以确保*$DIR*不作为文件存在:

if [ ! -d "$DIR" -a ! -e "$DIR" ]; then
  # Directory doesn't exist
  # Safe to create $DIR
  mkdir "$DIR"
fi

-e文件测试运算符将检查是否存在名为*$DIR的文件。因此,创建$DIR也不会与名为**$DIR*的现有文件发生冲突。

3. 替代方案:使用find工具

作为*-d*文件测试运算符的替代方法,我们还可以使用find 工具检查目录是否存在。

**我们可能需要使用find的原因之一是我们是否要检查是否存在与特定模式匹配的目录。**让我们在当前目录中检查名称以“photo”开头的目录:

if [ "$(find -maxdepth 1 -type d -name "photo*")" ]; then
  echo "$DIR exists."
else
  echo "$DIR doesn't exist."
fi

我们还可以执行find能够执行的其他有用检查,例如递归检查文件系统树中的目录是否存在或检查具有特定权限的目录。

4. 替代方案:使用ls命令

使用ls 是检查目录是否存在的另一种替代方法:

if [ "$(ls -- "$DIR" 2> /dev/null)" ]; then
  echo "$DIR exists."
else
  echo "$DIR doesn't exist."
fi