2012-09-27 23 views
91

Tôi có tuyên bố này:Làm cách nào để tạo thư mục nếu không tồn tại bằng cách sử dụng lớp File trong Ruby?

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

đâu

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

Những gì tôi muốn xảy ra là, nếu không có thư mục gọi là somedir hoặc some_subdir hoặc cả hai trong đường dẫn, tôi muốn nó automagically tạo nó.

Tôi có thể làm như thế nào?

Trả lời

107

Bạn có thể sử dụng FileUtils đệ quy tạo thư mục mẹ, nếu họ chưa có mặt:

require 'fileutils' 

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

Edit: Đây là một giải pháp sử dụng các thư viện lõi chỉ (reimplementing bánh xe, không khuyến khích)

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 
+4

FileUtils ** là ** trong stdlib: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html – Eureka

+0

Oh ok. Tôi có nghĩa là cốt lõi, không phải là stdlib. Dù bằng cách nào, đó là tốt. Những công việc này. Cảm ơn! – marcamillion

+1

Tôi đã thêm một giải pháp cốt lõi cho câu trả lời của mình: Hãy nhận biết, tuy nhiên, về cơ bản nó thực hiện 'FileUtils.mkdir_p' (là phương pháp dành riêng cho trường hợp sử dụng của bạn) – Eureka

54

đối với những người tìm kiếm một cách để tạo một thư mục nếu nó không tồn tại, đây là giải pháp đơn giản:

require 'fileutils' 

FileUtils.mkdir_p 'dir_name' 

Dựa trên Eureka's comment.

1

Cùng dòng tương tự (và tùy thuộc vào cấu trúc của bạn), đây là cách chúng tôi giải quyết nơi lưu ảnh chụp màn hình:

Trong thiết lập env của chúng tôi (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 

Và trong móc của chúng tôi. 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? 
15
directory_name = "name" 
Dir.mkdir(directory_name) unless File.exists?(directory_name) 
+0

Bạn có thể chạy vào điều kiện cuộc đua bằng cách sử dụng phương pháp này, thư mục có thể được tạo sau File.exists? chạy nhưng trước khi Dir.mkdir được thực hiện. –

3

Dựa trên những người khác câu trả lời, không có gì xảy ra (không làm việc). Không có lỗi và không có thư mục nào được tạo.

Đây là những gì tôi cần làm:

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

tôi cần phải tạo ra một biến để nắm bắt những phản ứng mà FileUtils.mkdir_p('dir_name') gửi lại ... sau đó tất cả mọi thứ đã làm việc như một nét duyên dáng!

+0

không có ý nghĩa. tại sao bạn cần nắm bắt lợi nhuận? –

+0

@huanson, tôi không cần phải bắt trả lại ... nhưng logic không hoạt động cho đến khi tôi tạo 'response = FileUtils.mkdir_p ('dir_name')'. Nếu tôi không tạo biến này, 'FileUtils.mkdir_p ('dir_name')' không hoạt động cho tôi ... hoặc ít nhất đó là những gì tôi nhớ đã xảy ra (câu trả lời này là hơn 1 năm). Tôi sẽ không ngạc nhiên nếu một phiên bản mới hơn của Ruby sửa lỗi này. – skplunkerin

1

Giải pháp duy nhất "thư viện cốt lõi" của câu trả lời hàng đầu chưa hoàn thành. Nếu bạn chỉ muốn sử dụng thư viện lõi, sử dụng như sau:

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 

tôi cần giải pháp này bởi vì sự phụ thuộc ngọc rmagick FileUtils' ngăn chặn ứng dụng Rails của tôi từ triển khai trên Amazon Web Services từ rmagick phụ thuộc vào gói libmagickwand-dev (Ubuntu)/imagemagick (OSX) hoạt động bình thường.

0

Cách sử dụng Pathname?

require 'pathname' 
some_path = Pathname("somedir/some_subdir/some-file.html") 
some_path.dirname.mkdir_p 
some_path.write(builder.to_html) 
Các vấn đề liên quan