Ruby에서 File 클래스를 사용하여 디렉토리가 없으면 어떻게 생성합니까?


121

나는이 진술이있다 :

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

어디

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

내가 원하는 것은 경로에 호출 된 디렉토리가 somedir없거나 some_subdir또는 둘 다 없는 경우 자동으로 생성하기를 원합니다.

어떻게 할 수 있습니까?

답변:


154

FileUtils를 사용하여 상위 디렉토리가 아직없는 경우 재귀 적으로 만들 수 있습니다.

require 'fileutils'

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

편집 : 다음은 핵심 라이브러리 만 사용하는 솔루션입니다 (휠 다시 구현, 권장하지 않음).

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의가 있다 다음 stdlib에서 : ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html
유레카

오 그래. 나는 stdlib가 아니라 핵심을 의미했습니다. 어느 쪽이든 괜찮습니다. 작동합니다. 감사!
marcamillion

1
나는 내 대답에 핵심 전용 솔루션을 추가했습니다. 그러나 본질적으로 다시 구현된다는 점 FileUtils.mkdir_p에 유의하십시오 (사용 사례 전용 방법)
Eureka

57
FileUtils#mkdir_p디렉토리 계층이 이미 존재하는 경우에도 작동이 솔루션이 할 수있는 하나 - 라이너로 압축 할 수 있도록 (그냥 아무것도하지 않는다) 플러스 문이 필요합니다FileUtils.mkdir_p(File.dirname(some_path))
유레카

1
@JosephK-나에게이 (오해의 소지가있는) EEXIST 오류는 결국 권한 문제가되었습니다.
TomG

81

존재하지 않는 경우 디렉토리만드는 방법을 찾는 사람들을 위해 다음 은 간단한 솔루션입니다.

require 'fileutils'

FileUtils.mkdir_p 'dir_name'

Eureka의 의견을 기반으로 합니다.


1
이것은 @Eureka의 코멘트입니다. "FileUtils # mkdir_p는 디렉토리 계층이 이미 존재하더라도 (아무것도하지 않음) 작동하므로이 솔루션을 한 줄로 압축하고 require 문으로 압축 할 수 있습니다. FileUtils.mkdir_p(File.dirname(some_path))"
Darpan

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

2
이 방법을 사용하면 경쟁 조건이 발생할 수 있습니다. File.exists 이후에 디렉토리가 생성 될 수 있습니까? Dir.mkdir이 실행되기 전에 실행됩니다.
Matt Fenelon 2016

4

다른 답변에 따르면 아무 일도 일어나지 않았습니다 (작동하지 않음). 오류가 없었고 디렉토리가 생성되지 않았습니다.

내가해야 할 일은 다음과 같습니다.

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

나는 FileUtils.mkdir_p('dir_name')다시 보내는 응답을 잡기 위해 변수를 만들어야했습니다 . 그러면 모든 것이 매력처럼 작동했습니다!


말이되지 않습니다. 왜 수익을 잡아야합니까?
Tim Kretschmer 2016 년

@huanson, 나는 반환을 잡을 필요가 없었습니다 ...하지만 논리는 내가 만들 때까지 작동하지 않았습니다 response = FileUtils.mkdir_p('dir_name'). 이 변수를 만들지 않았 FileUtils.mkdir_p('dir_name')거나 저를 위해 작동하지 않았다면 ... 또는 적어도 그것이 제가 기억하는 일입니다 (이 답변은 1 년 이상되었습니다). 최신 버전의 Ruby가이 문제를 해결하더라도 놀라지 않을 것입니다.
skplunkerin

2

사용은 Pathname어떻습니까?

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

1
그것은 작동 some_path.dirname.mkpath대신some_path.dirname.mkdir_p
마우로 Nidola

1
에 +1 mkpath. 또한 경로가 아닌 디렉토리 만 있으면 dirname, 예를 들어 Pathname ( "somedir / some_subdir"). mkpath는 같은 방식으로 작동합니다.
Michael

1

유사한 선 (그리고 구조에 따라)을 따라 스크린 샷을 저장할 위치를 다음과 같이 해결했습니다.

환경 설정 (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

그리고 우리의 hooks.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

최상위 답변의 "핵심 라이브러리"전용 솔루션은 불완전했습니다. 코어 라이브러리 만 사용하려면 다음을 사용하십시오.

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

rmagick가 제대로 작동하려면 libmagickwand-dev (Ubuntu) / imagemagick (OSX) 패키지에 의존하기 때문에 FileUtils의 종속성 gem rmagick가 내 Rails 앱이 Amazon Web Services에 배포되는 것을 막았 기 때문에이 솔루션이 필요했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.