How to create directories recursively in ruby? - ruby

I want to store a file as /a/b/c/d.txt, but I do not know if any of these directories exist and need to recursively create them if necessary.
How can one do this in ruby?

Use mkdir_p:
FileUtils.mkdir_p '/a/b/c'
The _p is a unix holdover for parent/path you can also use the alias mkpath if that makes more sense for you.
FileUtils.mkpath '/a/b/c'
In Ruby 1.9 FileUtils was removed from the core, so you'll have to require 'fileutils'.

Use mkdir_p to create directory recursively
path = "/tmp/a/b/c"
FileUtils.mkdir_p(path) unless File.exists?(path)

If you are running on unixy machines, don't forget you can always run a shell command under ruby by placing it in backticks.
`mkdir -p /a/b/c`

Pathname to the rescue!
Pathname('/a/b/c/d.txt').dirname.mkpath

require 'ftools'
File.makedirs

You could also use your own logic
def self.create_dir_if_not_exists(path)
recursive = path.split('/')
directory = ''
recursive.each do |sub_directory|
directory += sub_directory + '/'
Dir.mkdir(directory) unless (File.directory? directory)
end
end
So if path is 'tmp/a/b/c'
if 'tmp' doesn't exist 'tmp' gets created, then 'tmp/a/' and so on and so forth.

Related

FileUtils.mkdir_p support for wildcards in ruby?

I have for example directory structure like this:
./DIRECTORY/PROJECT_A/cars/
./DIRECTORY/PROJECT_B/planes/
./DIRECTORY/PROJECT_C/bikes/
I would like to recourse through them using wildcards and create other directory's, like this:
Dir['/DIRECTORY/PROJECT_*/*/'].each do FileUtils.mkdir_p 'TheNewDirectory'.
It seems "FileUtils" doesn't support wildcards.
I'm doing the same for creation of files on this way:
Dir['/DIRECTORY/PROJECT_*/*/'].each do |dir|
File.new File.join(dir, 'myFile.txt'), 'w+'
end
So I would like to do the same but for creation of directories. Any idea?
FileUtils is a module. It doesn't make sense to claim that a module "does not use wildcards".
Moreover, you are using only the function mkdir_p from FileUtils, and do not use any wildcard in its argument, so what you say, doesn't apply to your case either.
What happened is, that your are iterating through all the directories entries created by your Dir[...] expression, but then don't use the actual directory! A first step to write this better would be
Dir['/DIRECTORY/PROJECT_*/*/'].each { |d| FileUtils.mkdir_p("#{d}/TheNewDirectory") }
This works however only if it is guaranteed that d never takes the value of a plain file, and of course you can run this code only once (because the second time, you would obviously create directories of the form /DIRECTORY/PROJECT_FOO/BAR/TheNewDirectory/TheNewDirectory. I would therefore check, for the safe side, that it indeed makes sense to create the directory, before doing it.
To create directory, you need to specify full path of new directory using the current folder name:
Dir['/DIRECTORY/PROJECT_*/*/'].each do |f|
FileUtils.mkdir_p "#{f}/TheNewDirectory" if File.directory?(f)
end

How to change a file's path within ruby

I'm trying to move files from one folder to another via Ruby, but I'm stuck trying to get Pathname.new to work. For reference the files are being held in array as an inbetween from their normal dir. I know I could move it via CLI but I'd like the program to do it for me. This is what I have so far. I know it's wrong; I just don't get how to fix it.
temp_array.each {|song| song.path(Pathname.new("/Users/tsiege/Desktop/#{playlist_name}"))}
Have a look at FileUtils.mv:
require 'fileutils'
temp_array.each do |song|
FileUtils.mv song.path, "/Users/tsiege/Desktop/#{playlist_name}"
end
Be sure that the directory #{playlist_name} exists before you do, though:
FileUtils.mkdir_p "/Users/tsiege/Desktop/#{playlist_name}"
To move files you can use FileUtils.mv:
require 'fileutils'
FileUtils.mv 'from.ext', 'to.ext'
http://ruby-doc.org/stdlib-1.9.3/libdoc/fileutils/rdoc/FileUtils.html#method-c-mv
And if you want a list of files in a directory you can use:
Dir['/path/to/dir/*']
http://ruby-doc.org/core-1.9.3/Dir.html
Lastly, you may also want to check if you have a file or directory:
File.file? file
File.directory? dir
http://ruby-doc.org/core-1.9.3/File.html#method-c-file-3F

possible to indicate absolute path in ruby's require?

i discovered a problem when cron tries to run a ruby script which uses some library.
require "library"
#do some stuff
it complains about not being able to find library.rb
so i was wondering if i could do something like require "/var/dir/library.rb"
Yes, you can do that. You could also simply add the directory where your files are to the list of paths in $:, either with the -I argument, the RUBYLIB environment variable or just by doing $: << 'some_directory'.
if you're using 1.9
require_relative is your friend

Is it possible to recursively require all files in a directory in Ruby?

I am working on an API that needs to load all of the .rb files in its current directory and all subdirectories. Currently, I am entering a new require statement for each file that I add but I would like to make it where I only have to place the file in one of the subdirectories and have it automatically added.
Is there a standard command to do this?
In this case its loading all the files under the lib directory:
Dir["#{File.dirname(__FILE__)}/lib/**/*.rb"].each { |f| load(f) }
require "find"
Find.find(folder) do |file|
next if File.extname(file) != ".rb"
puts "loading #{file}"
load(file)
end
This will recursively load each .rb file.
like Miguel Fonseca said, but in ruby >= 2 you can do :
Dir[File.expand_path "lib/**/*.rb"].each{|f| require_relative(f)}
I use the gem require_all all the time, and it gets the job done with the following pattern in your requires:
require 'require_all'
require_all './lib/exceptions/'
def rLoad(dir)
Dir.entries(dir).each {|f|
next if f=='.' or f=='..'
if File.directory?(f)
rInclude(f)
else
load(f) if File.fnmatch('*.rb', f)
end
}
end
This should recursively load all .rb files in the directory specified by dir. For example, rLoad Dir.pwd would work on the current working directory.
Be careful doing this, though. This does a depth-first search and if there are any conflicting definitions in your Ruby scripts, they may be resolved in some non-obvious manner (alphabetical by folder/file name I believe).
You should have a look at this gem. It is quite small so you can actually re-use the code instead of installing the whole gem.

How can I make sure Ruby's Find module will always return absolute paths?

If I run the Find module with a relative directory as a parameter, the files returned by it will be relative ones. Can I do anything to make sure I always have absolute paths ?
require "find"
Find.find(dir) do |file|
# do I need to make it absolute myself? will File#extend_path be enough?
end
require 'find'
Find.find(File.expand_path(dir))
also seems to work.
Yes, expand_path will do it.
require 'find'
Find.find(dir) {|file| puts File.expand_path(file)}

Resources