递归mkdir


305

我是否忽略了一个Linux命令,该命令可以执行以下操作:(pseudo)

$ mkdir -R foo/bar/zoo/andsoforth

还是别无选择,只能一次创建一个目录?



1
有趣的是,我当时在浏览该页面,但完全忽略了“父母”,因为我认为他们是孩子(从左到右)。

18
普罗蒂普:在一些炮弹,你甚至可以做mkdir -p foo/{bar,baz}/zoo/andsoforth。很有用!
亚伦·科普利2012年

1
就个人而言,我也忽略了手册页中的“父”,因为,我觉得该标志应为“ -r”代表“递归”-或至少应该为该别名命名,因为mkdir只有6总共记录的标志。天哪,我觉得该命令默认情况下应该递归创建目录,如果您希望这样做,则必须明确指定。
jbowman '16

Answers:


511
$ mkdir -p foo/bar/zoo/andsoforth

92
仅供参考,-p代表“父母”
卡尔·克洛特

14
他们可以像其他任何命令一样使用-r来代替,这不可能记住每个linux命令的特定参数
Vedmant

2
mkdir -p不是跨平台的,并不在每个shell工作
РоманКоптев

9
@РоманКоптев,mkdir -p在POSIX规定,这是最接近被完全移植。您期望在Shell脚本中有什么更好的选择?
通配符

5
@StephanBijzitter是的,这是unix.se,而不是unixandwindows.se。:)
EEAA

16

mkdir -p对于大多数现代OS而言,使用是一种简单的方法:

mkdir -p foo/bar/zoo/andsoforth

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

跨平台安装和配置系统有自己的安全替代品mkdir -p

在命令行中使用的CMake:

 cmake -E make_directory foo/bar/zoo/andsoforth

要在脚本中进行预处理的Autoconf:

AS_MKDIR_P(foo/bar/zoo/andsoforth)

要么:

AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)

但是,这些解决方案需要cmakeautoconfM4)工具进行安装(和可能的预处理)

您还可以将install-sh脚本与-d选项一起使用:

install-sh -d foo/bar/zoo/andsoforth

该脚本由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
}

该脚本可用于没有选项-pfor的旧系统mkdir

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

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

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


4
“ mkdir -p”由posix定义。哪些unix或类似unix的变体不支持它?(而且它不应该是内置的shell,尽管我想没有任何理由不能这样做。)pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Tim B

5
该页面中的某些信息只有15年的历史。有些比较老。
Thomas Dickey

7
不支持的系统mkdir -p可能太旧了(而且我们谈论的至少已经有几十年了),以致没有printf实用程序或支持--来标记选项的终止。
斯特凡Chazelas

2
cdirname对于foo/bar//,或目录名称包含换行符或当前语言环境中的无效字符,您将给出错误的答案。
斯特凡Chazelas

2
printf在POSIX系统上是安全的。POSIX系统支持mkdir -pmkdir -pPOSIX已指定数十年了。--从80年代中期开始,从SysIII开始在AT&T系统上开始普及。我认为它最初是printf作为ksh内置函数出现的,后来由POSIX指定mkdir -p。某些POSIX shell(如基于pdksh或yash的)仍然没有printf内置。
斯特凡Chazelas

0

选项-p命令mkdir使p ARENT目录根据需要(没有错误,如果存在):

mkdir -p foo/bar/zoo/andsoforth

另一种方法是,例如,使用&&(如果指定的文件夹存在,则错误):

mkdir foo && mkdir foo/bar && mkdir foo/bar/zoo && mkdir foo/bar/zoo/andsoforth

链接运算符&&用于将命令链接在一起,以便仅当前一个命令没有错误退出时才运行下一个命令。

当然,第一种方法更好。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.