获取目录中的文件夹列表

我如何得到一个名单的文件夹存在于某个目录与红宝石?

Dir.entries()看起来很接近,但我不知道如何只限于文件夹。

69019 次浏览

I think you can test each file to see if it is a directory with FileTest.directory? (file_name). See the documentation for FileTest for more info.

You can use File.directory? from the FileTest module to find out if a file is a directory. Combining this with Dir.entries makes for a nice one(ish)-liner:

directory = 'some_dir'
Dir.entries(directory).select { |file| File.directory?(File.join(directory, file)) }

Edit: Updated per ScottD's correction.

Jordan is close, but Dir.entries doesn't return the full path that File.directory? expects. Try this:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}

In my opinion Pathname is much better suited for filenames than plain strings.

require "pathname"
Pathname.new(directory_name).children.select { |c| c.directory? }

This gives you an array of all directories in that directory as Pathname objects.

If you want to have strings

Pathname.new(directory_name).children.select { |c| c.directory? }.collect { |p| p.to_s }

If directory_name was absolute, these strings are absolute too.

I've found this more useful and easy to use:

Dir.chdir('/destination_directory')
Dir.glob('*').select {|f| File.directory? f}

it gets all folders in the current directory, excluded . and ...

To recurse folders simply use ** in place of *.

The Dir.glob line can also be passed to Dir.chdir as a block:

Dir.chdir('/destination directory') do
Dir.glob('*').select { |f| File.directory? f }
end

Recursively find all folders under a certain directory:

Dir.glob 'certain_directory/**/*/'

Non-recursively version:

Dir.glob 'certain_directory/*/'

Note: Dir.[] works like Dir.glob.

Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
$dir_target = "/Users/david/Movies/Camtasia 2/AzureMobileServices.cmproj/media"


Dir.glob("#{$dir_target}/**/*").each do |f|
if File.directory?(f)
puts "#{f}\n"
end
end

For a generic solution you probably want to use

Dir.glob(File.expand_path(path))

This will work with paths like ~/*/ (all folders within your home directory).

We can combine Borh's answer and johannes' answer to get quite an elegant solution to getting the directory names in a folder.

# user globbing to get a list of directories for a path
base_dir_path = ''
directory_paths = Dir.glob(File.join(base_dir_path, '*', ''))


# or recursive version:
directory_paths = Dir.glob(File.join(base_dir_path, '**', '*', ''))


# cast to Pathname
directories = directory_paths.collect {|path| Pathname.new(path) }


# return the basename of the directories
directory_names = directories.collect {|dir| dir.basename.to_s }

Only folders ('.' and '..' are excluded):

Dir.glob(File.join(path, "*", File::SEPARATOR))

Folders and files:

Dir.glob(File.join(path, "*"))

With this one, you can get the array of a full path to your directories, subdirectories, subsubdirectories in a recursive way. I used that code to eager load these files inside config/application file.

Dir.glob("path/to/your/dir/**/*").select { |entry| File.directory? entry }

In addition we don't need deal with the boring . and .. anymore. The accepted answer needed to deal with them.