Utwórz katalog, jeśli nie istnieje w Rubim

156

Próbuję utworzyć katalog z następującym kodem:

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

Jednak otrzymuję ten błąd:

Brak takiego pliku lub katalogu - / Users / Luigi / Desktop / Survey_Final / Archived / Survey / test (Errno :: ENOENT)

Dlaczego ten katalog nie jest tworzony za pomocą Dir.mkdirpowyższej instrukcji?

Luigi
źródło
4
File.exists?()działa na plikach i folderach. Nie zna różnicy.
Tin Man

Odpowiedzi:

263

Prawdopodobnie próbujesz utworzyć zagnieżdżone katalogi. Zakładając, fooże nie istnieje, otrzymasz no such file or directorybłąd dla:

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

Aby od razu utworzyć zagnieżdżone katalogi, FileUtilspotrzebne są:

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

Edit2: nie musisz używać FileUtils, możesz wykonać wywołanie systemowe (aktualizacja z @mu to zbyt krótki komentarz):

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

Ale wydaje mi się to (przynajmniej dla mnie) tak samo gorsze podejście, jak użycie zewnętrznego „narzędzia”, które może być niedostępne w niektórych systemach (chociaż trudno sobie wyobrazić system bez mkdir, ale kto wie).

zrl3dx
źródło
5
system 'mkdir', '-p', 'foo/bar'byłaby lepszą wersją tego systemwezwania. Nie ma potrzeby stosowania dodatkowego procesu powłoki ani zwykłego nonsensu dotyczącego cytowania / zmiany znaczenia / iniekcji, który pojawia się w wersji z pojedynczym argumentem system.
mu jest za krótkie
6
systemuruchomi się, /bin/shaby przeanalizować mkdir -p "foo/bar"ciąg, a następnie uruchomi się powłoka /bin/mkdir. Więc wykonujesz dodatkową pracę (utwórz ciąg polecenia, uruchom, /bin/shaby go ponownie rozdzielić), a część tej dodatkowej pracy pozostawia Cię otwartym na ataki polegające na wstrzykiwaniu powłoki (spędź trochę czasu w poradnikach CERT dla Rubiego, a zobaczysz, jak często ten problem jest).
mu jest za krótkie
1
@muistooshort @ zrl3dx Jak systempołączenie jest lepsze niż fileutilsponownie? Jestem w systemie Windows i mkdir_pdziała dobrze bez tworzenia podpowłoki tylko po to, aby przeanalizować, mkdir -pco i tak by się nie udało. Cieszę się, że fileutilsto pierwsza alternatywa w odpowiedzi.
TWiStErRob
1
@TWiStErRob: Przeczytaj jeszcze raz moje komentarze, nic nie powiedziałem fileutilslub mkdir_p, mówię tylko, że system command, arg1, arg2, ...jest lepsze niż system command_with_arguments.
mu jest za krótkie
3
@muistooshort ah, przepraszam, więc mówisz tylko, że jest lepszy sposób na zrobienie złej opcji :)
TWiStErRob
71

Prosta droga:

directory_name = "name"
Dir.mkdir(directory_name) unless File.exists?(directory_name)
Licysca
źródło
8
Należy używać File.directory? zamiast File.exists?
Florin Asăvoaie
4
Załóżmy, że istnieje normalny plik o tej samej nazwie. W takim przypadku nie można utworzyć katalogu.
Mikołaj Rozwadowski
3
Tworzy również stan wyścigu. Plik można utworzyć po sprawdzeniu, ale przed utworzeniem.
Don Reba,
25

Inny prosty sposób:

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

Štefan Bartoš
źródło
Jeśli chcesz tworzyć zagnieżdżone katalogi, to nie działa. Na przykład chciałem utworzyć następujący katalog, /home/jignesh/reports/testale podniesiono użycie tego rozwiązania RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir. Więc niezawodnym rozwiązaniem jest użycieFileUtils.mkdir_p
Jignesh Gohel
-5

A może po prostu Dir.mkdir('dir') rescue nil?

Vidar
źródło
3
Unikaj używania rescuew formie modyfikatora.
Sebastian Palma,
1
Zastanów się, dlaczego powinienem napisać 5 linii kodu zamiast tylko 1? Chciałbym zobaczyć, jak próbujesz.
Vidar
2
github.com/bbatsov/ruby-style-guide#no-rescue-modifiers spójrz, proszę
Sebastian Palma
1
Już to zrobiłem i całkowicie się nie zgadzam, myślę, że to głupie, więc może możesz mnie oświecić?
Vidar
6
Spowoduje to wykrycie każdego wyjątku, który nie jest tym, co próbujesz zrobić, aw prawdziwym świecie aplikacja ukryłaby problemy utrudniające konserwację. Ponadto używanie wyjątków jako warunków warunkowych nie jest dobrym pomysłem, ponieważ w sensie sprzętowym działają one znacznie wolniej (prawdopodobnie nie jest to problem we współczesnym języku, ale nadal sprawia, że ​​jako programista wyglądasz na niedoświadczonego).
Ed_