How to Check If a Given Directory Exists in Ruby

How to check if a given directory exists in Ruby

If it matters whether the file you're looking for is a directory and not just a file, you could use File.directory? or Dir.exist?. This will return true only if the file exists and is a directory.

As an aside, a more idiomatic way to write the method would be to take advantage of the fact that Ruby automatically returns the result of the last expression inside the method. Thus, you could write it like this:

def directory_exists?(directory)
File.directory?(directory)
end

Note that using a method is not necessary in the present case.

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.

Can't test if directory already exists from within Fastlane with Ruby

LOL Well, I discovered my issue. I didn't realize that I had to include the entire path to each of these statements, since I'm using Dir.foreach to iterate over part of the filesystem; the updated syntax is:

Dir.foreach(save_path) do |dir|
next if dir == '.' or dir == '..'
if (File.directory?("#{save_path}#{dir}"))
begin
FileUtils.mkdir_p("./#{save_path}#{dir}/images")
rescue StandardError => e
UI.message("Failed to make directory ./#{save_path}#{dir}/images: #{e.to_s}")
return
end
end
end

This is versus File.directory?("#{dir}") in that if statement. I thought that the Ruby Dir and FileUtil libraries would look relative to the current directory for the remainder of the path.

How to check if a directory/file/symlink exists with one command in Ruby

The standard File module has the usual file tests available:

RUBY_VERSION # => "1.9.2"
bashrc = ENV['HOME'] + '/.bashrc'
File.exist?(bashrc) # => true
File.file?(bashrc) # => true
File.directory?(bashrc) # => false

You should be able to find what you want there.


OP: "Thanks but I need all three true or false"

Obviously not. Ok, try something like:

def file_dir_or_symlink_exists?(path_to_file)
File.exist?(path_to_file) || File.symlink?(path_to_file)
end

file_dir_or_symlink_exists?(bashrc) # => true
file_dir_or_symlink_exists?('/Users') # => true
file_dir_or_symlink_exists?('/usr/bin/ruby') # => true
file_dir_or_symlink_exists?('some/bogus/path/to/a/black/hole') # => false

How to check if a directory exists in a Chef recipe NOT_IF?

I would suggest checking out out the ark cookbook for handling remote archive packages.

include_recipe "ark"

ark 'RevoMath' do
url 'https://mran.revolutionanalytics.com/install/RevoMath-1.0.1.tar.gz'
end

Which will install the tar package content into the /usr/local/RevoMath-1.0.1 directory. These defaults can be overridden.

How to check whether a File exists

File.exist? File.expand_path "~/dlds/some_file.ics"

Check if file/folder is in a subdirectory in Ruby

I hope I understood your question correct.

An example:

require 'pathname'

A = '/usr/xxx/a/b/c.txt'
path = Pathname.new(A)

[
'/usr/xxx/a/b',
'/usr/yyy/a/b',
].each{|b|

if path.fnmatch?(File.join(b,'**'))
puts "%s is in %s" % [A,b]
else
puts "%s is not in %s" % [A,b]
end
}

Result:

/usr/xxx/a/b/c.txt is in /usr/xxx/a/b
/usr/xxx/a/b/c.txt is not in /usr/yyy/a/b

The solution uses the class Pathname. An advantage of it: Pathname represents the name of a file or directory on the filesystem, but not the file itself. So you can make your test without a read access to the file.

The test itself is made with Pathname#fnmatch? and a glob-pattern File.join(path,'**') (** means all sub-directories).

If you need it more often, you could extend Pathname:

require 'pathname'
class Pathname
def is_underneath?(path)
return self.fnmatch?(File.join(path,'**'))
end
end

A = '/usr/xxx/a/b/c.txt'
path = Pathname.new(A)

[
'/usr/xxx/a/b',
'/usr/yyy/a/b',
].each{|b|
if path.is_underneath?(b)
puts "%s is in %s" % [A,b]
else
puts "%s is not in %s" % [A,b]
end
}

To handle absolute/relative pathes it may help to expand the pathes like in (sorry, this is untested).

class Pathname
def is_underneath?(path)
return self.expand_path.fnmatch?(File.expand_path(File.join(path,'**')))
end
end

Check if directory is empty in Ruby

Ruby now has Dir.empty?, making this trivially easy:

Dir.empty?('your_directory') # => (true|false)

In Rubies prior to 2.4.0 you can just get a list of the entries and see for yourself whether or not it's empty (accounting for "." and ".."). See the docs.

(Dir.entries('your_directory') - %w{ . .. }).empty?

# or using glob, which doesn't match hidden files (like . and ..)
Dir['your_directory/*'].empty?

Update: the first method above used to use a regex; now it doesn't (obviously). Comments below mostly apply to the former (regex) version.

Check if some files in array exist in directory

This is my solution after numerous attempts:

origin_files = ['test1.rb', 'test2.rb']
dir_path = "C:\\Test"

ruby_block "Rename file" do
block do
for filename in origin_files
newname = filename.split(".")[0] + '.origin'
if ::File.exist?("#{dir_path}\\#{newname}")
Chef::Log.info("### Your file: #{newname} already renamed ###")
else
::File.rename("#{dir_path}\\#{filename}", "#{dir_path}\\#{newname}")
end
end
end
end


Related Topics



Leave a reply



Submit