Ruby'de File sınıfını kullanarak hiçbiri yoksa nasıl dizin oluşturabilirim?


123

Bu ifadeye sahibim:

File.open(some_path, 'w+') { |f| f.write(builder.to_html)  }

Nerede

some_path = "somedir/some_subdir/some-file.html"

Hiçbir denilen dizin varsa ne olmasını istiyorsun, somedirya some_subdiryolda ya da her ikisi, ben automagicallylar bunu oluşturmak istiyorum.

Bunu nasıl yapabilirim?

Yanıtlar:


155

Halihazırda mevcut değilse, üst dizinleri özyinelemeli olarak oluşturmak için FileUtils'i kullanabilirsiniz:

require 'fileutils'

dirname = File.dirname(some_path)
unless File.directory?(dirname)
  FileUtils.mkdir_p(dirname)
end

Düzenleme: İşte yalnızca çekirdek kitaplıkları kullanan bir çözüm (tekerleğin yeniden uygulanması, önerilmez)

dirname = File.dirname(some_path)
tokens = dirname.split(/[\/\\]/) # don't forget the backslash for Windows! And to escape both "\" and "/"

1.upto(tokens.size) do |n|
  dir = tokens[0...n]
  Dir.mkdir(dir) unless Dir.exist?(dir)
end


Ah tamam. Çekirdeği kastetmiştim, stdlib'i değil. Her iki durumda da sorun değil. Bu çalışıyor. Teşekkürler!
marcamillion

1
Cevabıma yalnızca temel bir çözüm ekledim: Bununla birlikte, esasen yeniden FileUtils.mkdir_puygulandığını unutmayın (bu, kullanım örneğinize adanmış yöntemdir)
Eureka

57
Not FileUtils#mkdir_pdizin hiyerarşisi zaten var da çalışır bu çözüm bu kutu bir-liner içine sıkıştırılmış böylece (sadece hiçbir şey yapmaz) artı bir açıklama gerektirir:FileUtils.mkdir_p(File.dirname(some_path))
Eureka

1
@JosephK - benim için bu (yanıltıcı) EEXIST hatası bir izin sorunu olarak sona erdi.
TomG

82

Mevcut değilse bir dizin oluşturmanın bir yolunu arayanlar için , işte basit çözüm:

require 'fileutils'

FileUtils.mkdir_p 'dir_name'

Eureka'nın yorumuna göre .


1
Bu @ Eureka'nın yorumu - "FileUtils # mkdir_p'nin dizin hiyerarşisi zaten mevcut olsa bile çalıştığına dikkat edin (hiçbir şey yapmaz), bu nedenle bu çözüm tek satırlık bir kutu artı bir gereksinim ifadesi olarak sıkıştırılabilir: FileUtils.mkdir_p(File.dirname(some_path))"
Darpan

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

2
Bu yöntemi kullanarak yarış koşullarıyla karşılaşabilirsiniz, dizin File.exists'den sonra oluşturulabilir. çalışır ancak Dir.mkdir çalıştırılmadan önce.
Matt Fenelon

4

Başkalarının yanıtlarına göre hiçbir şey olmadı (işe yaramadı). Hata olmadı ve dizin oluşturulmadı.

İşte yapmam gerekenler:

require 'fileutils'
response = FileUtils.mkdir_p('dir_name')

FileUtils.mkdir_p('dir_name')Geri gönderilen yanıtı yakalamak için bir değişken oluşturmam gerekiyordu ... sonra her şey bir cazibe gibi çalıştı!


mantıklı değil. neden dönüşü yakalamalısın?
Tim Kretschmer

@huanson, dönüşü yakalamama gerek yoktu ... ama mantık oluşturana kadar işe yaramadı response = FileUtils.mkdir_p('dir_name'). Bu değişkeni ben yaratmadıysam, FileUtils.mkdir_p('dir_name')benim için çalışmıyor olsaydım ... ya da en azından bu olduğunu hatırlıyorum (bu cevap 1 yıldan daha eski). Ruby'nin daha yeni bir sürümü bu sorunu çözerse şaşırmam.
skplunkerin

2

Kullanmaya ne dersin Pathname?

require 'pathname'
some_path = Pathname("somedir/some_subdir/some-file.html")
some_path.dirname.mkdir_p
some_path.write(builder.to_html)

1
Onun some_path.dirname.mkpathyerine çalışırsome_path.dirname.mkdir_p
Mauro Nidola

1
+1 açık mkpath. Ayrıca yola değil de dizine sahipseniz, buna gerek yoktur dirname, örneğin Pathname ("somedir / bir_ubdir"). Mkpath aynı şekilde çalışacaktır.
Michael

1

Benzer çizgiler boyunca (ve yapınıza bağlı olarak), ekran görüntülerini nerede saklayacağımızı şu şekilde çözdük:

Env kurulumumuzda (env.rb)

screenshotfolder = "./screenshots/#{Time.new.strftime("%Y%m%d%H%M%S")}"
unless File.directory?(screenshotfolder)
  FileUtils.mkdir_p(screenshotfolder)
end
Before do
  @screenshotfolder = screenshotfolder
  ...
end

Ve kancalarımızda.rb

  screenshotName = "#{@screenshotfolder}/failed-#{scenario_object.title.gsub(/\s+/,"_")}-#{Time.new.strftime("%Y%m%d%H%M%S")}_screenshot.png";
  @browser.take_screenshot(screenshotName) if scenario.failed?

  embed(screenshotName, "image/png", "SCREENSHOT") if scenario.failed?

1

En üstteki yanıtın "çekirdek kitaplığı" tek çözümü eksikti. Yalnızca çekirdek kitaplıkları kullanmak istiyorsanız, aşağıdakileri kullanın:

target_dir = ""

Dir.glob("/#{File.join("**", "path/to/parent_of_some_dir")}") do |folder|
  target_dir = "#{File.expand_path(folder)}/somedir/some_subdir/"
end

# Splits name into pieces
tokens = target_dir.split(/\//)

# Start at '/'
new_dir = '/'

# Iterate over array of directory names
1.upto(tokens.size - 1) do |n|

  # Builds directory path one folder at a time from top to bottom
  unless n == (tokens.size - 1)
    new_dir << "#{tokens[n].to_s}/" # All folders except innermost folder
  else
    new_dir << "#{tokens[n].to_s}" # Innermost folder
  end

  # Creates directory as long as it doesn't already exist
  Dir.mkdir(new_dir) unless Dir.exist?(new_dir)
end

Bu çözüme ihtiyacım vardı çünkü FileUtils'in bağımlılığı gem rmagick, Rails uygulamamın Amazon Web Services üzerinde konuşlandırılmasını engelledi çünkü rmagick, libmagickwand-dev (Ubuntu) / imagemagick (OSX) paketinin düzgün çalışmasına bağlı.

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.