HOWTO · Bash

Bash 创建目录

本文演示了如何在 Bash 中不存在文件夹的情况下创建该文件夹。

本页内容

使用 mkdir -p -- "$directory",仅在目录不存在时创建它,并一并创建缺少的父目录。如果该路径已经是目录,命令会成功且不会更改它。如果该路径上已有普通文件,创建就会失败,因为文件不能充当目录。

在 Bash 中创建尚不存在的目录

mkdir 命令用于创建目录,不会创建文件。它的 -p 选项会创建缺少的父目录,并将已存在的目录视为成功。-- 表示选项到此结束;当目录名称以连字符开头时,这会很有用。为变量展开加上引号,可确保名称中的空格和通配符仍属于同一个路径。

使用 -d 测试来检查某个路径当前是否指向目录。方括号内的 Shell 语法需要空格:if [ -d "$directory" ]; then。这个测试能区分目录和文件,但无法保证后续命令一定成功:权限不足、目标路径上存在文件,或检查与创建之间路径发生变化,都可能导致 mkdir 无法创建目录。若只是要在目录不存在时创建它,mkdir -p 可以直接处理目录已存在的情况。

运行以下示例:

本节中的代码以及显示的标签或输出仍为英文。

if ! base=$(mktemp -d); then
  printf 'Could not create temporary directory.\n' >&2
  exit 1
fi
trap 'rm -rf "$base"' EXIT
directory="$base/reports"
if [ -d "$directory" ]; then
  printf 'Already present: %s\n' "${directory##*/}"
elif mkdir -p -- "$directory"; then
  printf 'Created: %s\n' "${directory##*/}"
else
  printf 'Could not create: %s\n' "${directory##*/}"
fi
Created: reports

提供的运行记录显示,程序输出了 Created: reports。如果 mktemp -d 失败,脚本会在设置目标路径、安装清理陷阱或调用 mkdir 之前退出。若命令成功,脚本结束时会删除临时路径。

使用 while 循环在 Bash 中创建目录

如果请求的目录已经存在,而你希望用户改选其他名称,可以使用 while 循环。使用 read -r 读取输入,避免反斜杠被特殊处理;为每个变量展开加上引号,并在输入结束时停止。下面是一个完整的交互式脚本:目录已存在或创建失败时会重新提示,mkdir 成功后则结束。按下 Ctrl+C 也会通过 Shell 结束脚本。

本节中的代码以及显示的标签或输出仍为英文。

#!/usr/bin/env bash
while :; do
  read -r -p 'Directory name: ' directory || break
  if [ -d "$directory" ]; then
    printf 'Directory already exists: %s\n' "$directory"
    continue
  fi
  if mkdir -p -- "$directory"; then
    printf 'Created: %s\n' "$directory"
    break
  fi
  printf 'Could not create: %s\n' "$directory"
done

提供的运行记录显示,该输入对应的执行过程没有产生标准输出。在交互式会话中,提示和消息会依输入的名称及当前位置的权限而有所不同。若只想创建一个目录且不再询问,请改用第一节中的直接命令 mkdir -p。

使用递归方法在 Bash 中创建目录

递归函数可以通过第一个参数 $1 接收要创建的路径。如果该路径已经是目录,函数会要求输入另一个名称,并用该输入再次调用自身。每次调用处理一个名称;这里没有可供跳出的循环。此脚本要求提供参数,会在创建前检查路径是否为目录,并在创建失败时报告错误,而不会误报成功。

本节中的代码以及显示的标签或输出仍为英文。

#!/usr/bin/env bash
mkdirectory() {
  local directory=$1
  local next_directory
  if [ -d "$directory" ]; then
    printf 'Directory already exists: %s\n' "$directory"
    read -r -p 'Enter a different path: ' next_directory || return 0
    mkdirectory "$next_directory"
  elif mkdir -p -- "$directory"; then
    printf 'Created: %s\n' "$directory"
  else
    printf 'Could not create: %s\n' "$directory"
  fi
}

if [ "$#" -lt 1 ]; then
  printf 'Usage: %s DIRECTORY\n' "$0"
  exit 0
fi
mkdirectory "$1"
Usage: case-3.sh DIRECTORY

将脚本保存为 rcrdir.sh,并传入一个路径来调用,例如 ./rcrdir.sh "project files"。如果没有提供参数,脚本会输出上方所示的用法提示并停止。提供的运行记录显示,执行时产生了该用法输出。如果请求的目录已经存在,请输入另一个路径;输入结束时,递归提示会正常停止。传入路径时的输出取决于参数和文件系统状态。