mkdir đệ quy


305

Có một lệnh linux mà tôi đang xem mà có thể thực hiện một số thứ theo dòng: (giả)

$ mkdir -R foo/bar/zoo/andsoforth

Hoặc không có cách nào khác ngoài việc tạo các thư mục cùng một lúc?



1
buồn cười, tôi đã xem trang đó nhưng hoàn toàn bỏ qua "cha mẹ" vì tôi nghĩ họ là trẻ con (trái sang phải).

18
Protip: Trong một số vỏ bạn thậm chí có thể làm mkdir -p foo/{bar,baz}/zoo/andsoforth. Rất hữu ích!
Aaron Copley

1
Cá nhân, tôi cũng bỏ qua "cha mẹ" trong trang người đàn ông bởi vì, tôi cảm thấy như cờ nên là "-r" cho "đệ quy" - hoặc ít nhất, nên có một bí danh cho như vậy vì mkdirchỉ có 6 cờ tài liệu trong tổng số. Chết tiệt, tôi cảm thấy như lệnh sẽ tạo các thư mục theo cách đệ quy theo mặc định và nếu bạn không muốn điều này thì bạn phải xác định rõ ràng như vậy.
jbowman

Câu trả lời:


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

92
FYI các -p viết tắt của "cha mẹ"
carl crott

14
Họ có thể đã thực hiện -r thay vào đó, giống như bất kỳ lệnh khác, đó là không thể nhớ các thông số cụ thể cho mỗi lệnh linux
Vedmant

2
Nhưng mkdir -pkhông phải là đa nền tảng, không hoạt động trong mọi vỏ
Công cụ tìm kiếm

9
@ Оооооооо, mkdir -pđược chỉ định trong POSIX , đây là thứ gần nhất để có thể mang theo hoàn toàn. Bạn mong đợi điều gì tốt hơn trong một kịch bản shell?
tự đại diện

5
@StephanBijzitter Yep, đây là unix.se, không phải unixandwindows.se. :)
EEAA

16

Sử dụngmkdir -p là một cách đơn giản cho hầu hết các hệ điều hành hiện đại:

mkdir -p foo/bar/zoo/andsoforth

Tuy nhiên, mkdir -pkhông được khuyến khích trong nhiều hướng dẫn. Đọc tài liệu về GNU makeautoconfvề các vấn đề khi sử dụng mkdir -p:

Các hệ thống cài đặt và cấu hình đa nền tảng có các lựa chọn thay thếmkdir -p an toàn cho riêng họ .

CMake để sử dụng trong dòng lệnh shell:

 cmake -E make_directory foo/bar/zoo/andsoforth

Autoconf để sử dụng trong tập lệnh với tiền xử lý:

AS_MKDIR_P(foo/bar/zoo/andsoforth)

hoặc là:

AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)

Nhưng các giải pháp này yêu cầu cmakehoặc autoconf( M4) các công cụ được cài đặt (và có thể tiền xử lý)

Bạn cũng có thể sử dụng install-shtập lệnh với -dtùy chọn:

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

Kịch bản này được sử dụng bởi autoconfautomakedự án. Tôi nghĩ rằng nó phải là giải pháp an toàn nhất.

Lúc đó tôi đang tìm kiếm một giải pháp đa nền tảng cho tiêu chuẩn /bin/shmà không phụ thuộc, nhưng vẫn chưa tìm thấy. Do đó, tôi đã viết kịch bản tiếp theo có thể không lý tưởng, nhưng tôi nghĩ nó phù hợp với hầu hết các yêu cầu đa nền tảng :

#! /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
}

Kịch bản này có thể được sử dụng cho các hệ thống cũ, nơi lựa chọn -pcho mkdirlà vắng mặt.

sedphiên bản đa nền tảng dựa trên dirnameđã được thêm vào mã. Nó hoạt động với một cách tương tự dirname(chính xác với đường dẫn /, đường dẫn chỉ có tên cơ sở, đường dẫn có dấu /, đường dẫn có và không có dấu \n). Hàm này không thể hoạt động chính xác nếu đường dẫn có dòng mới hoặc một số ký tự không hợp lệ cho miền địa phương hiện tại. Nó cũng thay thế bất kỳ sự kết hợp nào của /( //, ///) bằng một/

Thay đổi dòng mkdir "$1" || return 1thành test -d "$1" || { mkdir "$1" || return 1; }mkdirchấm dứt lỗi nếu đường dẫn tồn tại và kiểm tra này là cần thiết cho các đường dẫn có chứa các cấu trúc như aaa\.(Nếu aaakhông tồn tại phiên bản trước tạo aaavà sau đó cố gắng tạo lại nó).

Phiên bản mkd này không tạo ra lỗi nếu đường dẫn đã tồn tại (nhưng nó vẫn có khả năng tạo ra lỗi như vậy khi thực hiện song song) và không thể nhận được một số thư mục trong dòng lệnh.


4
"mkdir -p" được xác định bởi posix. Những biến thể unix hoặc unix nào không hỗ trợ nó? (và nó không phải là một vỏ tích hợp, mặc dù tôi đoán không có bất kỳ lý do nó không thể được.) pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Tim B

5
Một số thông tin trong trang đó chỉ mới 15 tuổi. Một số là cũ hơn.
Thomas Dickey

7
Các hệ thống không hỗ trợ mkdir -psẽ quá cũ (và chúng tôi đang nói ít nhất một vài thập kỷ) để có một printftiện ích hoặc hỗ trợ --để đánh dấu sự kết thúc của các tùy chọn.
Stéphane Chazelas

2
Bạn cdirnamesẽ đưa ra câu trả lời sai cho foo/bar//hoặc tên thư mục chứa ký tự dòng mới hoặc ký tự không hợp lệ trong ngôn ngữ hiện tại.
Stéphane Chazelas

2
printflà an toàn trên các hệ thống POSIX. Hỗ trợ hệ thống POSIX mkdir -p. mkdir -pđã được POSIX chỉ định trong nhiều thập kỷ. --bắt đầu phổ biến rộng rãi trên các hệ thống AT & T bắt đầu với SysIII vào đầu những năm giữa thập niên 80. Tôi tin rằng printflần đầu tiên xuất hiện dưới dạng kshnội dung và được POSIX chỉ định muộn hơn mkdir -p. Một số shell POSIX (như pdksh hoặc yash dựa) vẫn chưa được tích hợp printfsẵn.
Stéphane Chazelas

0

Tùy chọn -ptrong lệnh mkdirlàm cho p thư mục arent là cần thiết (không có lỗi nếu có):

mkdir -p foo/bar/zoo/andsoforth

Một cách khác là, ví dụ như sử dụng &&(lỗi nếu thư mục được chỉ định tồn tại):

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

Toán tử xích &&được sử dụng để xâu chuỗi các lệnh lại với nhau, sao cho lệnh tiếp theo được chạy khi và chỉ khi lệnh trước đó thoát mà không có lỗi.

Tất nhiên, cách đầu tiên là tốt hơn.


-3
mkdir foo foo/bar foo/bar/zoo/ foo/bar/zoo/andsofort.

Điều này nên làm điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.