Створіть Каталог, якщо він не існує в Ruby


156

Я намагаюся створити каталог із наступним кодом:

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

Однак я отримую цю помилку:

Немає такого файлу чи каталогу - / Користувачі / Luigi / Настільний / Survey_Final / Archived / Survey / test (Errno :: ENOENT)

Чому цей каталог не створюється Dir.mkdirвищевикладеним твердженням?


4
File.exists?()працює над файлами та папками. Не знає різниці.
Олов'яний чоловік

Відповіді:


263

Ви, ймовірно, намагаєтесь створити вкладені каталоги. Припускаючи, fooщо не існує, ви отримаєте no such file or directoryпомилку для:

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

Щоб створити вкладені каталоги відразу, FileUtilsпотрібно:

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

Edit2: вам не потрібно користуватися FileUtils, ви можете робити системний дзвінок (оновлення від @mu - це занадто короткий коментар):

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

Але це здається (принаймні для мене) таким же гіршим підходом, як ви використовуєте зовнішній "інструмент", який може бути недоступним для деяких систем (хоча я навряд чи уявляю систему без mkdir, але хто знає).


5
system 'mkdir', '-p', 'foo/bar'була б кращою версією цього systemдзвінка. Немає необхідності в додатковій оболонці або звичайному цитуванні / втечі / ін’єкції дурниць, що поставляється з єдиною версією аргументу system.
mu занадто короткий

6
systemзапуститься /bin/shдля розбору mkdir -p "foo/bar"рядка і тоді оболонка запуститься /bin/mkdir. Таким чином, ви займаєтесь додатковою роботою (створіть командний рядок, запустіть, /bin/shщоб знову розтягнути його), і частина цієї додаткової роботи залишає вас відкритими для атак ін'єкцій оболонки (проведіть деякий час у рекомендаціях CERT для Ruby, і ви побачите, як поширені ця проблема є).
mu занадто короткий

1
@muistooshort @ zrl3dx як systemдзвінок краще, ніж fileutilsзнову? Я на Windows іmkdir_p працює чудово, без нерестування підпрограми просто для розбору, mkdir -pякий все одно не вдасться. Радий, що fileutilsце перша альтернатива у відповіді.
TWiStErRob

1
@TWiStErRob: Ще раз прочитайте мої коментарі, я нічого не говорив про це fileutils те чи mkdir_pвсе , що я хочу сказати, що system command, arg1, arg2, ...це краще , ніж system command_with_arguments.
mu занадто короткий

3
@muistooshort ах, вибачте, тому ви просто говорите, що є кращий спосіб зробити поганий варіант :)
TWiStErRob

71

Простий спосіб:

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

8
Слід використовувати File.directory? а не File.exists?
Флорін Асвойої

4
Припустимо, є звичайний файл з такою ж назвою. У такому випадку ви не можете створити каталог.
Mikołaj Rozwadowski

3
Це також створює умову гонки. Файл може бути створений після перевірки, але перед створенням.
Дон Реба

25

Ще один простий спосіб:

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


Якщо ви хочете створити вкладені каталоги, це не працює. Наприклад, я хотів створити наступний каталог, /home/jignesh/reports/testале використовуючи це рішення, підняте RUBY (Errno::ENOENT), no such file or directory @ dir_s_mkdir. Тож застосовується надійне рішенняFileUtils.mkdir_p
Jignesh Gohel

-5

Як щодо Dir.mkdir('dir') rescue nil?


3
Уникайте використання rescueу формі модифікатора.
Себастьян Пальма

1
Потрібно пояснити, чому я повинен написати 5 рядків коду, а не лише 1? Мені б хотілося, щоб ви спробували.
Відар


1
Я вже це робив, і я абсолютно не згоден, я думаю, що це нерозумно, тож, може, ти можеш мене просвітити?
Відар

6
Це дозволить уникнути будь-якого винятку, який не є тим, що ви намагаєтеся зробити, і в реальному додатку буде приховано проблеми, що ускладнюють обслуговування. Крім того, не дуже гарна ідея використовувати винятки як умовні, в апаратному розумінні вони працюють набагато повільніше (швидше за все, це не проблема в сучасній мові, але все ж змушує вас виглядати недосвідченим як кодер).
Ред
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.