mkdir rekursif

305

Apakah ada perintah linux yang saya abaikan yang memungkinkan untuk melakukan sesuatu di sepanjang baris: (pseudo)

$ mkdir -R foo/bar/zoo/andsoforth

Atau tidak ada alternatif selain membuat direktori satu per satu?

Braiam
sumber
1
lucu, saya melihat halaman itu tetapi "orangtua" benar-benar diabaikan karena saya menganggap mereka sebagai anak-anak (kiri ke kanan).
18
Protip: Dalam beberapa shell Anda bahkan dapat melakukannya mkdir -p foo/{bar,baz}/zoo/andsoforth. Sangat berguna!
Aaron Copley
1
Secara pribadi, saya mengabaikan "orangtua" di halaman manual juga karena, yah, saya merasa bendera harus "-r" untuk "rekursif" - atau paling tidak, harus ada alias untuk itu karena mkdirhanya memiliki 6 total bendera terdokumentasi. Sial, saya merasa seperti perintah harus membuat direktori secara rekursif secara default, dan jika Anda tidak ingin ini maka Anda harus menentukannya secara eksplisit.
Jbowman
1
stackoverflow.com/questions/1731767/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

511
$ mkdir -p foo/bar/zoo/andsoforth
EEAA
sumber
92
FYI the -p adalah singkatan dari "parents"
carl crott
14
Mereka bisa membuat -r sebagai gantinya, seperti perintah lainnya, itu tidak mungkin untuk mengingat parameter khusus untuk setiap perintah linux
Vedmant
2
Tapi mkdir -pini bukan lintas platform, tidak berfungsi di setiap shell
Роман Коптев
9
@ РоманКоптев, mkdir -pyang ditentukan dalam POSIX , yang merupakan hal yang paling dekat untuk menjadi sepenuhnya portabel. Apa yang lebih baik dari yang Anda harapkan dalam skrip shell?
Wildcard
5
@StephanBijzitter Yap, ini unix.se, bukan unixandwindows.se. :)
EEAA
16

Menggunakanmkdir -p adalah cara sederhana untuk sebagian besar OS modern:

mkdir -p foo/bar/zoo/andsoforth

Namun, mkdir -ptidak direkomendasikan dalam banyak manual. Baca dokumentasi untuk GNU makedan autoconftentang masalah dalam menggunakan mkdir -p:

Instalasi lintas platform dan sistem konfigurasi memiliki alternatifmkdir -p amannya sendiri .

CMake untuk digunakan di baris perintah shell:

 cmake -E make_directory foo/bar/zoo/andsoforth

Autoconf untuk digunakan dalam skrip dengan preprocessing:

AS_MKDIR_P(foo/bar/zoo/andsoforth)

atau:

AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)

Tetapi solusi ini membutuhkan cmakeatau autoconf( M4) alat untuk diinstal (dan kemungkinan preprocessing)

Anda juga dapat menggunakan install-shskrip dengan -dopsi:

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

Script ini digunakan oleh autoconfdan automakeproyek. Saya pikir itu harus menjadi solusi teraman.

Saat itu saya sedang mencari solusi lintas platform untuk standar /bin/shtanpa ketergantungan, tetapi belum menemukannya. Oleh karena itu saya menulis skrip berikutnya yang mungkin tidak ideal, tetapi saya pikir itu sesuai dengan sebagian besar persyaratan lintas platform :

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

Skrip ini dapat digunakan untuk sistem lama, di mana opsi -puntuk mkdirtidak ada.

sedVersi lintas platform berbasis dirnameditambahkan ke kode. Ia bekerja dengan cara yang mirip dengan dirname(benar dengan path /, path dengan nama dasar saja, path dengan trailing /, path dengan dan tanpa trailing \ns). Fungsi ini tidak dapat berfungsi dengan benar jika jalur memiliki baris baru atau beberapa karakter yang tidak valid untuk lokal saat ini. Itu juga menggantikan kombinasi /( //, ///) dengan tunggal/

Baris yang diubah mkdir "$1" || return 1menjadi test -d "$1" || { mkdir "$1" || return 1; }karena mkdirberakhir dengan kesalahan jika jalur ada dan pemeriksaan ini diperlukan untuk jalur yang berisi konstruksi seperti aaa\.(Jika aaatidak ada versi sebelumnya membuat aaadan kemudian mencoba untuk membuatnya lagi).

Versi mkd ini tidak menghasilkan kesalahan jika path sudah ada (tetapi masih memiliki kemungkinan untuk menghasilkan kesalahan seperti itu dalam eksekusi paralel) dan tidak bisa mendapatkan beberapa direktori di command line.

Роман Коптев
sumber
4
"mkdir -p" didefinisikan oleh posix. Apa varian unix atau unix-like yang tidak mendukungnya? (dan seharusnya bukan shell built-in, meskipun saya kira tidak ada alasannya.) pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Tim B
5
Beberapa informasi di halaman itu baru berusia 15 tahun. Beberapa lebih tua.
Thomas Dickey
7
Sistem yang tidak mendukung mkdir -pakan terlalu tua (dan kita berbicara setidaknya beberapa dekade) untuk memiliki printfutilitas atau dukungan --untuk menandai akhir opsi.
Stéphane Chazelas
2
Anda cdirnameakan memberikan jawaban yang salah untuk foo/bar//, atau nama direktori yang mengandung karakter baris baru, atau karakter yang tidak valid di lokal saat ini.
Stéphane Chazelas
2
printfaman pada sistem POSIX. Dukungan sistem POSIX mkdir -p. mkdir -ptelah ditentukan oleh POSIX selama beberapa dekade. --mulai menyebar luas pada sistem AT&T yang dimulai dengan SysIII pada awal pertengahan pertengahan 80-an. printfpertama kali muncul sebagai kshbuiltin saya percaya dan ditentukan oleh POSIX lebih lambat dari mkdir -p. Beberapa shell POSIX (seperti pdksh atau berbasis yash) masih belum memiliki printfbuiltin.
Stéphane Chazelas
0

Opsi -pdalam perintah mkdirmembuat direktori p arent sesuai kebutuhan (tidak ada kesalahan jika ada):

mkdir -p foo/bar/zoo/andsoforth

Cara lain adalah, misalnya menggunakan &&(kesalahan jika folder yang ditentukan ada):

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

Operator chaining &&digunakan untuk mengaitkan perintah bersama, sehingga perintah selanjutnya dijalankan jika dan hanya jika perintah sebelumnya keluar tanpa kesalahan.

Tentu saja, cara pertama lebih baik.

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

Ini harus dilakukan.

Kanchan Kumar
sumber