mkdir แบบเรียกซ้ำ


305

มีคำสั่ง linux หรือไม่ที่ฉันมองข้ามซึ่งทำให้สามารถทำบางสิ่งได้ตามบรรทัด: (หลอก)

$ mkdir -R foo/bar/zoo/andsoforth

หรือไม่มีทางเลือกอื่นนอกจากทำไดเร็กตอรี่ทีละไฟล์?



1
ตลกฉันกำลังดูหน้านั้น แต่มองข้าม "พ่อแม่" โดยสิ้นเชิงเพราะฉันคิดว่าพวกเขาเป็นเด็ก (จากซ้ายไปขวา)

18
protip: mkdir -p foo/{bar,baz}/zoo/andsoforthในเปลือกหอยบางอย่างที่คุณสามารถทำได้แม้กระทั่ง มีประโยชน์มาก!
Aaron Copley

1
โดยส่วนตัวฉันมองข้าม "ผู้ปกครอง" ในหน้าคนด้วยเพราะฉันรู้สึกว่าธงควรเป็น "-r" สำหรับ "recursive" - ​​หรืออย่างน้อยที่สุดควรมีชื่อแทนเนื่องจากmkdirมีเพียง 6 เอกสารทั้งหมดรวมธง นรกฉันรู้สึกว่าคำสั่งควรสร้างไดเรกทอรีซ้ำโดยค่าเริ่มต้นและหากคุณไม่ต้องการสิ่งนี้คุณควรระบุอย่างชัดเจน
jbowman

คำตอบ:


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

92
FYI -p ย่อมาจาก "
parent

14
พวกเขาสามารถสร้าง -r แทนเช่นเดียวกับคำสั่งอื่น ๆ ซึ่งเป็นไปไม่ได้ที่จะจำพารามิเตอร์เฉพาะสำหรับคำสั่ง linux ทุกคำ
Vedmant

2
แต่mkdir -pไม่ใช่แพลตฟอร์มข้ามไม่สามารถใช้งานได้ในทุกเชลล์
РоманКоптев

9
@ РоманКоптев mkdir -pถูกระบุใน POSIXซึ่งเป็นสิ่งที่ใกล้เคียงกับการพกพาได้อย่างเต็มที่ คุณคาดหวังอะไรในเชลล์สคริปต์ดีกว่า
Wildcard

5
@StephanBijzitter ใช่นี่คือ unix.se ไม่ใช่ unixandwindows.se :)
EEAA

16

การใช้mkdir -pเป็นวิธีที่ง่ายสำหรับระบบปฏิบัติการที่ทันสมัยที่สุด:

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)

แต่โซลูชั่นเหล่านี้ต้องใช้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
}

สคริปต์นี้สามารถนำมาใช้สำหรับระบบเก่าที่ตัวเลือก-pสำหรับการmkdirขาด

sed-based แพลตฟอร์มข้ามเวอร์ชันของdirnameถูกเพิ่มไปยังรหัส มันทำงานด้วยวิธีที่คล้ายกับdirname(แก้ไขด้วยพา ธ/, พา ธที่มีชื่อฐานเท่านั้น, พา ธ ที่มีการต่อท้าย/, พา ธ ที่มีและไม่มีการต่อท้าย\n) ฟังก์ชันนี้ไม่สามารถทำงานได้อย่างถูกต้องหากเส้นทางมีการขึ้นบรรทัดใหม่หรืออักขระที่ไม่ถูกต้องสำหรับสถานที่ปัจจุบัน นอกจากนี้ยังแทนที่การรวมกันของ/( //, ///) ด้วยซิงเกิล/

เปลี่ยนบรรทัดmkdir "$1" || return 1เป็นtest -d "$1" || { mkdir "$1" || return 1; }เพราะmkdirยุติด้วยข้อผิดพลาดหากมีเส้นทางอยู่และต้องใช้การตรวจสอบนี้สำหรับเส้นทางที่มีสิ่งปลูกสร้างเช่นaaa\.(หากaaaไม่มีอยู่เวอร์ชันก่อนหน้าจะสร้างขึ้นaaaจากนั้นลองสร้างอีกครั้ง)

mkd รุ่นนี้ไม่ได้สร้างข้อผิดพลาดหากเส้นทางมีอยู่แล้ว (แต่ก็ยังมีความเป็นไปได้ที่จะสร้างข้อผิดพลาดในการประมวลผลแบบขนาน) และไม่สามารถรับหลายไดเรกทอรีในบรรทัดคำสั่ง


4
"mkdir -p" ถูกกำหนดโดย posix Unix หรือ Unix-like มีรูปแบบใดบ้างที่ไม่รองรับ (และมันก็ไม่ควรเป็นเชลล์ในตัว แต่ฉันคิดว่าไม่มีเหตุผลใด ๆ ที่มันไม่สามารถทำได้) pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Tim B

5
ข้อมูลบางส่วนในหน้านั้นมีอายุเพียง 15 ปี บางคนแก่กว่า
Thomas Dickey

7
ระบบที่ไม่รองรับmkdir -pจะเก่าเกินไป (และเรากำลังพูดถึงอย่างน้อยสองสามทศวรรษ) เพื่อให้มีprintfยูทิลิตี้หรือการสนับสนุน--เพื่อทำเครื่องหมายจุดสิ้นสุดของตัวเลือก
Stéphane Chazelas

2
คุณcdirnameจะให้คำตอบที่ผิดfoo/bar//หรือชื่อไดเรกทอรีที่มีอักขระขึ้นบรรทัดใหม่หรืออักขระที่ไม่ถูกต้องในภาษาปัจจุบัน
Stéphane Chazelas

2
printfมีความปลอดภัยในระบบ POSIX mkdir -pสนับสนุนระบบ POSIX mkdir -pได้รับการระบุโดย POSIX มานานหลายทศวรรษ --เริ่มแพร่หลายในระบบ AT&T ที่เริ่มต้นด้วย SysIII ในช่วงกลางยุค 80 printfปรากฏตัวครั้งแรกในฐานะkshbuiltin ผมเชื่อและถูกระบุโดย POSIX mkdir -pช้ากว่า POSIX shells บางตัว (เช่น pdksh หรือ yash based) ยังไม่มีprintfbuiltin
Stéphane 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

โอเปอเรเตอร์ chaining &&ใช้ในการโยงคำสั่งเข้าด้วยกันเช่นว่าคำสั่งถัดไปจะทำงานถ้าหากคำสั่งก่อนหน้านี้ออกโดยไม่มีข้อผิดพลาด

แน่นอนวิธีแรกดีกว่า


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.