Ruby'de yoksa Dizin Oluştur


156

Aşağıdaki kod ile bir dizin oluşturmaya çalışıyorum:

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

Ancak, bu hatayı alıyorum:

Böyle bir dosya veya dizin yok - / Kullanıcılar / Luigi / Masaüstü / Survey_Final / Arşivlenmiş / Survey / test (Errno :: ENOENT)

Bu dizin neden Dir.mkdiryukarıdaki ifade tarafından oluşturulmuyor ?


4
File.exists?()dosya ve klasörler üzerinde çalışır. Farkı bilmiyor.
Tin Man

Yanıtlar:


263

Büyük olasılıkla iç içe dizinler oluşturmaya çalışıyorsunuz. fooVar olmadığı varsayıldığında , aşağıdakiler için no such file or directoryhata alırsınız :

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

Bir kerede iç içe dizinler oluşturmak FileUtilsiçin gereklidir:

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

Edit2: kullanmak zorunda değilsiniz, FileUtilssistem çağrısı yapabilirsiniz (@mu'dan güncelleme çok kısa yorumdur):

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

Ancak bu, (en azından benim için), bazı sistemlerde bulunamayan harici 'aracı' kullandığınız kadar kötü bir yaklaşım gibi görünüyor (ancak sistemi olmadan hayal bile edemiyorum mkdir, ama kim bilir).


5
system 'mkdir', '-p', 'foo/bar'bu systemçağrının daha iyi bir sürümü olurdu . Ekstra kabuk işlemine veya tek argüman sürümü ile gelen olağan alıntı / kaçış / enjeksiyon saçmalıklarına gerek yoktur system.
mu

6
systemdizeyi /bin/shayrıştırmak için başlatılacak mkdir -p "foo/bar"ve sonra kabuk çalışacaktır /bin/mkdir. Ekstra iş yapıyorsunuz (komut dizesini oluşturun, /bin/shyeniden ayırmak için başlatın ) ve bu ekstra işlerden bazıları sizi kabuk enjeksiyon saldırılarına açık bırakır (Ruby için CERT tavsiyelerinde biraz zaman geçirin ve ne kadar yaygın olduğunu göreceksiniz. bu sorun).
mu

1
@muistooshort @ zrl3dx Çağrı nasıl systemdaha iyi fileutils? Windows'tayım ve yine de başarısız olacak mkdir_payrıştırmak için bir alt kabuk yumurtlamadan gayet iyi çalışıyor mkdir -p. Bunun fileutilscevabındaki ilk alternatif olduğuna sevindim .
TWiStErRob

1
@TWiStErRob: Yorumlarımı tekrar oku, hakkında hiçbir şey söylemedim ya fileutilsda mkdir_ptek söylediğim system command, arg1, arg2, ...daha iyi system command_with_arguments.
mu çok kısa

3
@muistooshort ah, üzgünüm, bu yüzden sadece kötü seçeneği yapmanın daha iyi bir yolu olduğunu söylüyorsun :)
TWiStErRob

71

Basit yol:

directory_name = "name"
Dir.mkdir(directory_name) unless File.exists?(directory_name)

8
File.directory kullanılsın mı? File.exist yerine?
Florin Asăvoaie

4
Aynı ada sahip normal bir dosya olduğunu varsayalım. Böyle bir durumda dizin oluşturamazsınız.
Mikołaj Rozwadowski

3
Ayrıca bir yarış durumu yaratır. Dosya çekten sonra ancak oluşturulmadan önce oluşturulabilir.
Don Reba

25

Başka bir basit yol:

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


İç içe dizinler oluşturmak istiyorsanız, bu işe yaramaz. Örneğin ben aşağıdaki dizini oluşturmak istedim /home/jignesh/reports/testama bu çözümü kullanarak kaldırdı RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir. Yani güvenilir çözüm kullanıyorFileUtils.mkdir_p
Jignesh Gohel

-5

Sadece nasıl Dir.mkdir('dir') rescue nil?


3
rescueDeğiştirici formda kullanmaktan kaçının .
Sebastian Palma

1
Neden sadece 1 yerine 5 satır kod yazmam gerektiğini açıklamak ister misiniz? Denediğini görmek istiyorum.
Vidar


1
Zaten yaptım ve tamamen katılmıyorum, bence saçma, belki de beni aydınlatabilirsin?
Vidar

6
Bu, yapmaya çalıştığınız herhangi bir istisnayı yakalar ve gerçek bir dünya uygulamasında, bakımı zorlaştıran sorunları gizler. Ayrıca, istisnaları koşullu olarak kullanmak harika bir fikir değildir, donanım anlamında çok daha yavaş çalışırlar (muhtemelen modern bir dilde bir sorun değildir, ancak yine de bir kodlayıcı olarak deneyimsiz görünmenizi sağlar).
Ed_
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.