Create Directory If It Doesn't Exist with Ruby

Create Directory if it doesn't exist with Ruby

You are probably trying to create nested directories. Assuming foo does not exist, you will receive no such file or directory error for:

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

To create nested directories at once, FileUtils is needed:

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

Edit2: you do not have to use FileUtils, you may do system call (update from @mu is too short comment):

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

But that seems (at least to me) as worse approach as you are using external 'tool' which may be unavailable on some systems (although I can hardly imagine system without mkdir, but who knows).

How do I create directory if none exists using File class in Ruby?

You can use FileUtils to recursively create parent directories, if they are not already present:

require 'fileutils'

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

Edit: Here is a solution using the core libraries only (reimplementing the wheel, not recommended)

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

How do I create a subdirectory if no one exists when writing to a CSV file?

You can do this:

require "fileutils"

csvfile= 'tmp/folder1/folder2/folder3/foo.csv'

FileUtils::mkdir_p File.dirname csvfile

mkdir_p is line gnu mkdir -p which creates the directory structure for you, and won't complain if the directory already exists.

dirname returns the directory name.

If you want specify permissions when creating the directory do this:

FileUtils::mkdir_p( File.dirname(csvfile) , :mode => 0777)

How to create a folder (if not present) with Logger.new?

Try something like this.

  dir = File.dirname("#{Rails.root}/log/#{today}/my.log")

FileUtils.mkdir_p(dir) unless File.directory?(dir)

@@my_logger ||= Logger.new("#{Rails.root}/log/#{today}/my.log")

How to create directories recursively 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'.

Creating directory over SFTP on Ruby fails if directory exists already

In this case, it may be better to simply "ask for forgiveness", then to "ask for permission". It also eliminates a race condition, where you check if the directory exists, discover it doesn't, and then while creating it you error out because it was created by someone else in the meantime.

The following code will work better:

Net::SFTP.start( ip, id, :password => pass, :port=> port ) do |sftp|
begin
sftp.mkdir! remotePath
rescue Net::SFTP::StatusException => e
# verify if this returns 11. Your server may return
# something different like 4.
if e.code == 11
# directory already exists. Carry on..
else
raise
end
end
sftp.upload!(localPath + localfile, remotePath + remotefile)
end

Check if path is a directory path (it might not exist)


TL;DR

If the Pathname isn't on the filesystem already, it's just a name. Its type (e.g. file or directory) isn't fixed until you create a filesystem object with it. So, I recommend either unambiguously constructing each directory Pathname with a trailing separator, or using the Pathname to create the file or directory with the relevant methods for its intended type.

Testing Pathname Objects with Trailing Directory Separator

If you're using the Pathname module, the Pathname doesn't have to exist to be used. In such cases, it's useful to note that the Ruby engine converts forward slashes into backslashes when on Windows, so the following constructed pathnames should work on Windows, Linux, MacOS, and Unix:


Pathname('/some/path/').to_s.end_with? ?/
#=> true

Pathname('C:/some/path/').to_s.end_with? ?/
#=> true

However, if your Pathname is constructed manually or programmatically without being read in from the filesystem or using File#join, you may need to use a character class to check for both *nix and Windows trailing separators. For example:

require 'pathname'

%w[ /some/path/ C:\\some\\path\\ ].map do |path|
Pathname(path).to_s.match? %r![/\\]\z!
end
#=> [true, true]

Using Method to Set Filesystem Object Type

If you construct a path without a trailing directory separator but the directory doesn't actually exist in the filesystem, then you can't determine just from the name whether it's supposed to be a file or directory. A Pathname is really just a special type of String object. The documentation explicitly states (emphasis mine):

Pathname represents the name of a file or directory on the filesystem, but not the file itself.

That being the case, your best bet is to modify your Pathname constructor to ensure that you're building names with trailing separators in the first place. If you can't or won't do that, you will have to leave it up to your filesystem writing code to explicitly call an appropriate method explicitly on the expected filesystem object. For example:

require 'pathname'
require 'fileutils'

path = Pathname '/tmp/foo'

# ensure file or directory doesn't already exist
path.rmtree

# use path as file
FileUtils.touch path
path.file?
#=> true

# remove path before next test
path.unlink

# use path as directory
path.mkpath
path.directory?
#=> true

As you can see, a Pathname without a trailing (back)slash can be used for both files and directories, depending on how you use it.

Ruby unable to create directories

The error is in the line:

line.chomp

It strips the newline from the tail of line and returns a value that is ignored. It doesn't change the value of line. It still ends with "\n" and this is a character that is not allowed in file names on Windows. The code runs fine on Linux and creates directories whose names end in "\n".

The solution is also simple. Use #chomp! instead:

#require 'fileutils'

value=File.open('D:\\exercise\\list.txt').read
value.gsub!(/\r\n?/, "\n")
value.each_line do |line|
line.chomp!
print "FOlder names:#{line}"
Dir.mkdir("D:\\exercise\\#{line}")
end

(It might still produce errors, however, because of empty lines in the input).

FileUtils.mkdir can not create a directory

you need FileUtils.mkdir_p "/tmp/bar/foo"

mkdir_p behaves exactly as mkdir -p on UNIXes - if some dir does not exists it will be created.

I bet there are no /tmp/bar dir and Ruby fails to create a dir into an non-existing folder.



Related Topics



Leave a reply



Submit