Buat Direktori jika tidak ada dengan Ruby

156

Saya mencoba membuat direktori dengan kode berikut:

Dir.mkdir("/Users/Luigi/Desktop/Survey_Final/Archived/Survey/test")
    unless File.exists?("/Users/Luigi/Desktop/Survey_Final/Archived/Survey/test")  

Namun, saya menerima kesalahan ini:

Tidak ada file atau direktori tersebut - / Pengguna / Luigi / Desktop / Survey_Final / Diarsipkan / Survei / uji (Errno :: ENOENT)

Mengapa direktori ini tidak dibuat oleh Dir.mkdirpernyataan di atas?

Luigi
sumber
4
File.exists?()bekerja pada file dan folder. Tidak tahu bedanya.
the Tin Man

Jawaban:

263

Anda mungkin mencoba membuat direktori bersarang. Dengan asumsi footidak ada, Anda akan menerima no such file or directorykesalahan untuk:

Dir.mkdir 'foo/bar'
# => Errno::ENOENT: No such file or directory - 'foo/bar'

Untuk membuat direktori bersarang sekaligus, FileUtilsdiperlukan:

require 'fileutils'
FileUtils.mkdir_p 'foo/bar'
# => ["foo/bar"]

Sunting2: Anda tidak harus menggunakan FileUtils, Anda dapat melakukan panggilan sistem (pembaruan dari @mu adalah komentar terlalu pendek):

> system 'mkdir', '-p', 'foo/bar' # worse version: system 'mkdir -p "foo/bar"'
=> true

Tapi itu tampaknya (setidaknya bagi saya) sebagai pendekatan yang lebih buruk karena Anda menggunakan 'alat' eksternal yang mungkin tidak tersedia pada beberapa sistem (walaupun saya tidak bisa membayangkan sistem tanpa mkdir, tapi siapa yang tahu).

zrl3dx
sumber
5
system 'mkdir', '-p', 'foo/bar'akan menjadi versi yang lebih baik dari systempanggilan itu. Tidak perlu untuk proses shell tambahan atau kutipan / melarikan diri / injeksi omong kosong biasa yang datang dengan versi argumen tunggal system.
mu terlalu pendek
6
systemakan memulai /bin/shuntuk mengurai mkdir -p "foo/bar"string dan kemudian shell akan berjalan /bin/mkdir. Jadi Anda melakukan pekerjaan ekstra (membuat string perintah, luncurkan /bin/shuntuk memisahkannya lagi) dan beberapa pekerjaan tambahan itu membuat Anda terbuka untuk serangan injeksi shell (menghabiskan waktu di penasihat CERT untuk Ruby dan Anda akan melihat seberapa umum masalah ini).
mu terlalu pendek
1
@muistooshort @ zrl3dx bagaimana systempanggilan lebih baik daripada fileutilslagi? Saya di Windows dan mkdir_pberfungsi dengan baik tanpa memunculkan subkulit hanya untuk mengurai mkdir -pyang akan gagal pula. Senang itu fileutilsadalah alternatif pertama dalam jawabannya.
TWiStErRob
1
@TWiStErRob: Baca komentar saya lagi, saya tidak mengatakan apa-apa tentang , fileutilsatau yang mkdir_psaya katakan adalah itu system command, arg1, arg2, ...lebih baik daripada system command_with_arguments.
mu terlalu pendek
3
@muistooshort ah, maaf, jadi Anda hanya mengatakan bahwa ada cara yang lebih baik untuk melakukan opsi buruk :)
TWiStErRob
71

Cara sederhana:

directory_name = "name"
Dir.mkdir(directory_name) unless File.exists?(directory_name)
Licysca
sumber
8
Anda harus menggunakan File.directory? daripada File.exists?
Florin Asăvoaie
4
Misalkan ada file normal dengan nama yang sama. Anda tidak dapat membuat direktori dalam kasus seperti itu.
Mikołaj Rozwadowski
3
Ini juga menciptakan kondisi balapan. File dapat dibuat setelah cek tetapi sebelum pembuatan.
Don Reba
25

Cara sederhana lain:

Dir.mkdir('tmp/excel') unless Dir.exist?('tmp/excel')

Štefan Bartoš
sumber
Jika Anda ingin membuat direktori bersarang maka ini tidak berfungsi. Untuk misalnya saya ingin membuat direktori berikut /home/jignesh/reports/testtetapi menggunakan solusi ini dimunculkan RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir. Jadi solusi yang dapat diandalkan adalah menggunakanFileUtils.mkdir_p
Jignesh Gohel
-5

Bagaimana dengan adil Dir.mkdir('dir') rescue nil?

Vidar
sumber
3
Hindari penggunaan rescuedalam bentuk pengubahnya.
Sebastian Palma
1
Ingin menjelaskan mengapa saya harus menulis 5 baris kode, bukan hanya 1? Saya ingin melihat Anda mencoba.
Vidar
1
Saya sudah melakukannya, dan saya benar-benar tidak setuju, saya pikir itu konyol, jadi mungkin Anda dapat mencerahkan saya?
Vidar
6
Ini akan menangkap setiap pengecualian yang tidak apa yang Anda coba lakukan dan dalam aplikasi dunia nyata akan menyembunyikan masalah membuat perawatan lebih keras. Juga, ini bukan ide yang bagus untuk menggunakan pengecualian sebagai persyaratan, dalam arti perangkat keras mereka berjalan jauh lebih lambat (kemungkinan tidak benar-benar masalah dalam bahasa modern tetapi masih membuat Anda terlihat tidak berpengalaman sebagai pembuat kode).
Ed_