遞歸 mkdir
是否有一個我忽略的 linux 命令可以執行以下操作:(偽)
$ mkdir -R foo/bar/zoo/andsoforth
或者除了一次創建一個目錄之外別無選擇?
$ mkdir -p foo/bar/zoo/andsoforth
參數
p
代表“父母”。
**對於大多數現代作業系統來說,使用
mkdir -p
**是一種簡單的方法:mkdir -p foo/bar/zoo/andsoforth
但是,
mkdir -p
在許多手冊中並不推薦。閱讀 GNU 的文件make
以及autoconf
關於使用的問題mkdir -p
:
- http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Limitations-of-Usual-Tools.html#Limitations-of-Usual-Tools
- http://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/Utilities-in-Makefiles.html
跨平台安裝和配置系統有自己的安全替代方案
mkdir -p
。在 shell 命令行中使用的 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)
但是這些解決方案需要
cmake
或autoconf
(M4
) 安裝工具(以及可能的預處理)您還可以使用帶有選項
install-sh
的腳本:-d
install-sh -d foo/bar/zoo/andsoforth
該腳本由
autoconf
和automake
項目使用。我認為這一定是最安全的解決方案。當時我正在尋找一種
/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 }
此腳本可用於沒有 for 選項的舊
-p
系統mkdir
。
sed
-基於跨平台的版本dirname
被添加到程式碼中。它的工作方式類似於dirname
(正確使用 path/
,僅帶有基本名稱的路徑,帶有尾隨/
的路徑,帶有和不帶有尾隨\n
s 的路徑)。如果路徑包含換行符或目前語言環境的某些無效字元,則此功能無法正常工作。/
它還將(//
, ) 的任何組合替換///
為單個/
將行更改
mkdir "$1" || return 1
為test -d "$1" || { mkdir "$1" || return 1; }
因為mkdir
如果路徑存在則以錯誤終止,並且對於包含結構的路徑需要此檢查aaa\.
(如果aaa
不存在以前的版本創建aaa
然後嘗試再次創建它)。如果 path 已經存在,這個版本的 mkd 不會產生錯誤(但它仍然有可能在並行執行中產生這樣的錯誤)並且無法在命令行中獲取多個目錄。