Crea directory se non esiste con Ruby


156

Sto cercando di creare una directory con il seguente codice:

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

Tuttavia, sto ricevendo questo errore:

Nessun file o directory di questo tipo - / Users / Luigi / Desktop / Survey_Final / Archiviato / Survey / test (Errno :: ENOENT)

Perché questa directory non viene creata Dir.mkdirdall'istruzione precedente?


4
File.exists?()funziona su file e cartelle. Non conosce la differenza.
Tin Man,

Risposte:


263

Probabilmente stai cercando di creare directory nidificate. Supponendo fooche non esista, riceverai un no such file or directoryerrore per:

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

Per creare directory nidificate contemporaneamente, FileUtilsè necessario:

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

Edit2: non è necessario utilizzare FileUtils, è possibile effettuare chiamate di sistema (l'aggiornamento da @mu è un commento troppo breve):

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

Ma questo sembra (almeno per me) un approccio peggiore di quello che stai usando "strumento" esterno che potrebbe non essere disponibile su alcuni sistemi (anche se non riesco quasi a immaginarlo senza mkdir, ma chi lo sa).


5
system 'mkdir', '-p', 'foo/bar'sarebbe una versione migliore di quella systemchiamata. Non è necessario un ulteriore processo di shell o la solita assurdità di quoting / escape / injection fornita con la versione a argomento singolo di system.
mu è troppo corto il

6
systemverrà avviato /bin/shper analizzare la mkdir -p "foo/bar"stringa e quindi verrà eseguita la shell /bin/mkdir. Quindi stai facendo un lavoro extra (crea la stringa di comando, avviala /bin/shper smontarla di nuovo) e parte di quel lavoro extra ti lascia aperto agli attacchi di shell injection (trascorri un po 'di tempo negli avvisi CERT per Ruby e vedrai quanto è comune questo problema è).
mu è troppo corto il

1
@muistooshort @ zrl3dx come è systemmeglio una chiamata fileutils? Sono su Windows e mkdir_pfunziona benissimo senza generare una subshell solo per analizzare mkdir -pche comunque fallirebbe. Sono contento che fileutilssia la prima alternativa nella risposta.
TWiStErRob

1
@TWiStErRob: Leggi di nuovo i miei commenti, di cui non ho detto nulla fileutilso mkdir_p, tutto quello che sto dicendo è che system command, arg1, arg2, ...è meglio di system command_with_arguments.
mu è troppo corto il

3
@muistooshort ah, scusa, quindi stai solo dicendo che c'è un modo migliore di fare la cattiva opzione :)
TWiStErRob

71

Modo semplice:

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

8
Si deve usare File.directory? piuttosto che File.exists?
Florin Asăvoaie,

4
Supponiamo che ci sia un file normale con lo stesso nome. In tal caso, non è possibile creare una directory.
Mikołaj Rozwadowski il

3
Inoltre crea una condizione di razza. Il file può essere creato dopo il controllo ma prima della creazione.
Don Reba,

25

Un altro modo semplice:

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


Se si desidera creare directory nidificate, questo non funziona. Per esempio, volevo creare la seguente directory /home/jignesh/reports/testma usando questa soluzione sollevata RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir. Quindi la soluzione affidabile sta usandoFileUtils.mkdir_p
Jignesh Gohel il

-5

Che ne dici di solo Dir.mkdir('dir') rescue nil?


3
Evitare l'uso rescuenella sua forma di modificatore.
Sebastian Palma,

1
Vuoi spiegare perché dovrei scrivere 5 righe di codice anziché solo 1? Mi piacerebbe vederti provare.
Vidar,


1
L'ho già fatto e non sono assolutamente d'accordo, penso che sia sciocco, quindi forse puoi illuminarmi?
Vidar,

6
Ciò catturerebbe qualsiasi eccezione che non è ciò che stai cercando di fare e in un'app del mondo reale nasconderebbe problemi che rendono più difficile la manutenzione. Inoltre, non è una grande idea usare le eccezioni come condizionali, in senso hardware corrono molto più lentamente (probabilmente non è un problema in un linguaggio moderno ma ti fa sembrare inesperto come programmatore).
Ed_
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.