递归 mkdir

442 mkdir

是否有我忽略的 linux 命令可以执行以下操作:(伪)

$ mkdir -R foo/bar/zoo/andsoforth
Run Code Online (Sandbox Code Playgroud)

或者除了一次创建一个目录之外别无选择?

EEA*_*EAA 712

$ mkdir -p foo/bar/zoo/andsoforth
Run Code Online (Sandbox Code Playgroud)

参数p代表“父母”。

  • 完全有道理,我认为 -r 代表权限。 (2认同)

小智 23

mkdir -p对于大多数现代操作系统来说,使用是一种简单的方法:

mkdir -p foo/bar/zoo/andsoforth
Run Code Online (Sandbox Code Playgroud)

但是,mkdir -p在许多手册中都不推荐使用。阅读 GNU 的文档make以及autoconf有关使用的问题mkdir -p

跨平台安装和配置系统对于mkdir -p.

在 shell 命令行中使用的 CMake:

 cmake -E make_directory foo/bar/zoo/andsoforth
Run Code Online (Sandbox Code Playgroud)

Autoconf 在脚本中使用预处理:

AS_MKDIR_P(foo/bar/zoo/andsoforth)
Run Code Online (Sandbox Code Playgroud)

或者:

AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)
Run Code Online (Sandbox Code Playgroud)

但是这些解决方案需要安装cmakeautoconf( M4) 工具(以及可能的预处理)

您还可以使用install-sh带有-d选项的脚本:

install-sh -d foo/bar/zoo/andsoforth
Run Code Online (Sandbox Code Playgroud)

该脚本由autoconfautomake项目使用。我认为这一定是最安全的解决方案。

当时我正在寻找一种/bin/sh没有依赖性的标准跨平台解决方案,但还没有找到。因此我写了下一个可能不太理想的脚本,但我认为它符合大多数跨平台要求

#! /bin/sh

cdirname() # cross platform alternative for 'dirname'
{
  # $1 - path
  test $# -eq 1 || { echo "Procedure 'cdirname' must have only one parameter. Scripting error."; exit 1; }
  echo "$1" | sed -n -e '1p' | sed  -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' -
}

mkd() # cross platform alternative for 'mkdir -p'
{
  # $1 - directory to create
  test $# -eq 1 || { echo "Function 'mkd' can create only one directory (with it's parent directories)."; exit 1; }
  test -d "$1"  && return 0
  test -d "$(cdirname "$1")" || { mkd "$(cdirname "$1")" || return 1; }
  test -d "$1" || { mkdir "$1" || return 1; }
  return 0
}
Run Code Online (Sandbox Code Playgroud)

该脚本可以使用旧系统,其中选择-pmkdir是不存在的。

sed-基于跨平台版本的dirname已添加到代码中。它的工作方式类似于dirname(使用 path 正确,/仅带有基本名称的路径,带有尾随的/路径,带有和不带有尾随\ns 的路径)。如果路径有换行符或当前语言环境的某些无效字符,则此功能无法正常工作。它还将/( //, ///) 的任意组合替换为单个/

将行更改mkdir "$1" || return 1test -d "$1" || { mkdir "$1" || return 1; }因为mkdir如果路径存在则以错误终止,并且对于包含类似结构的路径需要此检查aaa\.(如果aaa不存在先前版本创建aaa然后尝试再次创建它)。

如果路径已经存在,这个版本的 mkd 不会产生错误(但它仍然有可能在并行执行中产生这样的错误)并且无法在命令行中获取多个目录。

  • 不支持 `mkdir -p` 的系统会太旧(我们说的是至少有几十年的历史),无法使用 `printf` 实用程序或支持 `--` 来标记选项的结束。 (7认同)
  • 该页面中的某些信息只有 15 年的历史。有些年纪大了。 (5认同)
  • “mkdir -p”由 posix 定义。哪些 unix 或类 Unix 变体不支持它?(它不应该是内置的 shell,但我想没有任何理由不能。)http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html (4认同)
  • 你的 `cdirname` 会给出错误的 `foo/bar//` 答案,或者包含换行符的目录名,或者当前语言环境中的无效字符。 (2认同)
  • `printf` 在 POSIX 系统上是安全的。POSIX 系统支持`mkdir -p`。`mkdir -p` 已经被 POSIX 指定了几十年。`--` 从 80 年代中期的 SysIII 开始,开始在 AT&T 系统上广泛使用。我相信 `printf` 最初是作为 `ksh` 内置函数出现的,并且在 `mkdir -p` 之后由 POSIX 指定。一些 POSIX shell(如基于 pdksh 或 yash 的)仍然没有内置 `printf`。 (2认同)
  • 我在这些链接中看到的关于 `mkdir -p` 的唯一抱怨是同时执行 `mkdir -pa/b` 和 `mkdir -pa/c` 时的竞争条件,其中都需要创建 `a/`,但是第二个调用 `mkdir(2)` 的进程发现另一个进程已经创建了它。这在交互式使用中不是问题,当然也不是“少数系统不支持它”。此外,我认为关于在 makefile 中使用哪些实用程序的 gnu make 文档不适用于该上下文之外。更可能出现的是支持 `-p` 的 `mkdir` 还是 `autoconf`?对我来说,前者。 (2认同)