I want to get all file names from a folder using Ruby.
19 Answers
You also have the shortcut option of
Dir["/path/to/search/*"]
and if you want to find all Ruby files in any folder or sub-folder:
Dir["/path/to/search/**/*.rb"]

- 51,832
- 12
- 88
- 127

- 7,297
- 1
- 17
- 20
-
6Or you can do the same with Dir::glob() – Yoann Le Touche Nov 18 '09 at 14:43
-
2Also, use `./...` rather than `~/` – Minh Triet Aug 05 '14 at 04:20
-
5Why is this prefered? – BvuRVKyUVlViVIc7 Feb 06 '15 at 11:51
-
1@MinhTriet what does that do? What is it preferable? – stephenmurdoch Apr 08 '15 at 22:30
-
9@marflar - `./` means the current directory, whereas `/` is the root mount point, and `~/` is the user's home directory. If you move the whole project somewhere else, the first one will work, but the other two probably won't. – mirichan Jul 10 '15 at 05:34
-
Note that Dir["/path/to/search/**/*.*"] will also return folders/sub-folders with a '.' in their name. You need to do an extra check with File.file?(file_or_folder_name) to catch them. – dwkns Jan 29 '17 at 12:46
Dir.entries(folder)
example:
Dir.entries(".")
Source: http://ruby-doc.org/core/classes/Dir.html#method-c-entries

- 7,051
- 5
- 41
- 47

- 56,372
- 28
- 94
- 125
-
17Looks like he's using SO to document the answers to questions he's just asked. A sort of memo, I suppose. Can't see much wrong with that - after all, even though this one is a little incomplete (`Dir#glob` could have perhaps been mentioned, for instance) there's nothing to prevent someone else from posting a Really Good Answer. 'course, I'm mostly a "glass half full" sort of a guy... – Mike Woodhouse Nov 18 '09 at 13:05
-
1@Mike: In the grand scheme of things, it's probably not a big deal. And as you say if the questions and answers were good, it could be a plus overall for the site. But here both question and answer are so minimal that it doesn't seem especially useful. – Telemachus Nov 18 '09 at 13:11
-
25@Telemachus I use `Dir` rarely, and every time I need it I have to read documentation. I have posted my question and answer here so I could find it later, and maybe even help someone with the same question. I think I have heard at SO podcast that there is nothing wrong with such behavior. If you have a better answer, please post it. I have posted what I know, I am not a Ruby ninja. I regularly accept answers with the most votes. – Željko Filipin Nov 19 '09 at 10:42
-
This can be a better option than `Dir[]` or `Dir.glob` when the argument is a variable. When `path = '/tmp'`, compare: `Dir.glob("#{path}/*")` vs `Dir.entries(path)`. The return values are slightly different (".", ".."), but the latter is easier to grok on a quick glance. – Benjamin Oakes May 02 '13 at 21:09
-
1Dir.entries will return a list that includes "." and "..". If you don't want those, you can use Dir.each_child. – Jun 21 '21 at 22:16
-
-
This also returns directories (and not just `.` and `..`). While directories technically are files, that isn't typically what people mean when they say "files". There are better answers... – Huliax Dec 20 '21 at 21:12
-
Self-answers are encouraged, but that doesn't exempt the question from the normal requirements. This thread doesn't pose a question or show any research, just happened to be the first to pick a piece of low-hanging fruit back in 2009. – ggorlen Oct 11 '22 at 18:26
The following snippets exactly shows the name of the files inside a directory, skipping subdirectories and "."
, ".."
dotted folders:
Dir.entries("your/folder").select { |f| File.file? File.join("your/folder", f) }

- 4,783
- 2
- 34
- 50

- 24,390
- 8
- 55
- 67
-
21Can also do `...select {|f| File.file? f}` for clearer meaning and shorter syntax. – Automatico Nov 04 '13 at 18:19
-
2I'm seeing Dir.entries not give the full path in return filename so this solution didn't work for me. – James McMahon Feb 27 '14 at 15:49
-
2@squixy Did you write it out correctly?: `Dir.entries("your/folder").select {|f| File.file? f}` – Automatico Apr 07 '14 at 13:57
-
10
-
2@squixy I had the same problem, in my case I need to provide the full path not just the file name returned by Dir.foreach – TheLukeMcCarthy May 05 '14 at 21:00
-
1FYI Dir.glob returns full path and filename, Dir.entries does not. You have to have the full path and filename for either File.file? or File.directory? to work correctly. – Tony Nov 24 '14 at 21:03
-
6`.reject {|f| File.directory? f}` seems cleaner than `.select{|f| !File.directory? f}`. Oh, and now I see the first comment... also good. – Ian May 26 '15 at 17:28
-
1The reason File.file? doesn't work is because you're passing a file name instead of the absolute path to that file. File.file?("#{path}/#{file}") should work. – moeabdol Sep 25 '15 at 14:08
-
adding to the list of options ... `.reject!{|file_name| [".","..",".gitignore"].include?(file_name)}` – s2t2 Jan 22 '16 at 23:22
To get all files (strictly files only) recursively:
Dir.glob('path/**/*').select { |e| File.file? e }
Or anything that's not a directory (File.file?
would reject non-regular files):
Dir.glob('path/**/*').reject { |e| File.directory? e }
Alternative Solution
Using Find#find
over a pattern-based lookup method like Dir.glob
is actually better. See this answer to "One-liner to Recursively List Directories in Ruby?".

- 4,783
- 2
- 34
- 50

- 72,135
- 12
- 99
- 105
This works for me:
If you don't want hidden files[1], use Dir[]:
# With a relative path, Dir[] will return relative paths
# as `[ './myfile', ... ]`
#
Dir[ './*' ].select{ |f| File.file? f }
# Want just the filename?
# as: [ 'myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.basename f }
# Turn them into absolute paths?
# [ '/path/to/myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.absolute_path f }
# With an absolute path, Dir[] will return absolute paths:
# as: [ '/home/../home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }
# Need the paths to be canonical?
# as: [ '/home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }.map{ |f| File.expand_path f }
Now, Dir.entries will return hidden files, and you don't need the wildcard asterix (you can just pass the variable with the directory name), but it will return the basename directly, so the File.xxx functions won't work.
# In the current working dir:
#
Dir.entries( '.' ).select{ |f| File.file? f }
# In another directory, relative or otherwise, you need to transform the path
# so it is either absolute, or relative to the current working dir to call File.xxx functions:
#
home = "/home/test"
Dir.entries( home ).select{ |f| File.file? File.join( home, f ) }
[1] .dotfile
on unix, I don't know about Windows
In Ruby 2.5 you can now use Dir.children
. It gets filenames as an array except for "." and ".."
Example:
Dir.children("testdir") #=> ["config.h", "main.rb"]

- 3,468
- 2
- 27
- 38
Personally, I found this the most useful for looping over files in a folder, forward looking safety:
Dir['/etc/path/*'].each do |file_name|
next if File.directory? file_name
end

- 158,662
- 42
- 215
- 303

- 685
- 1
- 9
- 18
This is a solution to find files in a directory:
files = Dir["/work/myfolder/**/*.txt"]
files.each do |file_name|
if !File.directory? file_name
puts file_name
File.open(file_name) do |file|
file.each_line do |line|
if line =~ /banco1/
puts "Found: #{line}"
end
end
end
end
end

- 2,598
- 1
- 16
- 15
this code returns only filenames with their extension (without a global path)
Dir.children("/path/to/search/")
=> [file_1.rb, file_2.html, file_3.js]

- 591
- 6
- 6
-
Nice explanation here: https://www.bigbinary.com/blog/ruby-2_5-introduces-dir-children-and-dir-each_child – fguillen Mar 12 '22 at 13:24
While getting all the file names in a directory, this snippet can be used to reject both directories [.
, ..
] and hidden files which start with a .
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}

- 158,662
- 42
- 215
- 303

- 1,684
- 4
- 31
- 35
-
`Dir.entries` returns local file names, not absolute file paths. On the other hand, `File.directory?` expects an absolute file path. This code does not work as expected. – Nathan Jan 27 '16 at 01:33
-
It's weird the code doesn't work in your case. As this is a code I have used in a live app which works just fine. I'll recheck my code and post here if there is anything missing from my original working code :) – Lahiru Jayaratne Jan 27 '16 at 01:54
-
1
-
1This answer is a duplicate of [the answer](https://stackoverflow.com/a/15511438/3676469) added in 2013 – Hirurg103 Sep 02 '20 at 00:59
This is what works for me:
Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }
Dir.entries
returns an array of strings. Then, we have to provide a full path of the file to File.file?
, unless dir
is equal to our current working directory. That's why this File.join()
.

- 102,010
- 123
- 446
- 597
-
1
-
1This answer is a duplicate of [the answer](https://stackoverflow.com/a/15511438/3676469) added in 2013 – Hirurg103 Sep 02 '20 at 01:01
You may also want to use Rake::FileList
(provided you have rake
dependency):
FileList.new('lib/*') do |file|
p file
end
According to the API:
FileLists are lazy. When given a list of glob patterns for possible files to be included in the file list, instead of searching the file structures to find the files, a FileList holds the pattern for latter use.

- 6,024
- 2
- 37
- 34
One simple way could be:
dir = './' # desired directory
files = Dir.glob(File.join(dir, '**', '*')).select{|file| File.file?(file)}
files.each do |f|
puts f
end

- 31
- 2
When loading all names of files in the operating directory you can use
Dir.glob("*)
This will return all files within the context that the application is running in (Note for Rails this is the top level directory of the application)
You can do additional matching and recursive searching found here https://ruby-doc.org/core-2.7.1/Dir.html#method-c-glob

- 1,717
- 1
- 10
- 8
def get_path_content(dir)
queue = Queue.new
result = []
queue << dir
until queue.empty?
current = queue.pop
Dir.entries(current).each { |file|
full_name = File.join(current, file)
if not (File.directory? full_name)
result << full_name
elsif file != '.' and file != '..'
queue << full_name
end
}
end
result
end
returns file's relative paths from directory and all subdirectories

- 2,738
- 3
- 23
- 41
If you want get an array of filenames including symlinks, use
Dir.new('/path/to/dir').entries.reject { |f| File.directory? f }
or even
Dir.new('/path/to/dir').reject { |f| File.directory? f }
and if you want to go without symlinks, use
Dir.new('/path/to/dir').select { |f| File.file? f }
As shown in other answers, use Dir.glob('/path/to/dir/**/*')
instead of Dir.new('/path/to/dir')
if you want to get all the files recursively.

- 2,421
- 1
- 24
- 31
In addition to the suggestions in this thread, I wanted to mention that if you need to return dot files as well (.gitignore, etc), with Dir.glob you would need to include a flag as so:
Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH)
By default, Dir.entries includes dot files, as well as current a parent directories.
For anyone interested, I was curious how the answers here compared to each other in execution time, here was the results against deeply nested hierarchy. The first three results are non-recursive:
user system total real
Dir[*]: (34900 files stepped over 100 iterations)
0.110729 0.139060 0.249789 ( 0.249961)
Dir.glob(*): (34900 files stepped over 100 iterations)
0.112104 0.142498 0.254602 ( 0.254902)
Dir.entries(): (35600 files stepped over 100 iterations)
0.142441 0.149306 0.291747 ( 0.291998)
Dir[**/*]: (2211600 files stepped over 100 iterations)
9.399860 15.802976 25.202836 ( 25.250166)
Dir.glob(**/*): (2211600 files stepped over 100 iterations)
9.335318 15.657782 24.993100 ( 25.006243)
Dir.entries() recursive walk: (2705500 files stepped over 100 iterations)
14.653018 18.602017 33.255035 ( 33.268056)
Dir.glob(**/*, File::FNM_DOTMATCH): (2705500 files stepped over 100 iterations)
12.178823 19.577409 31.756232 ( 31.767093)
These were generated with the following benchmarking script:
require 'benchmark'
base_dir = "/path/to/dir/"
n = 100
Benchmark.bm do |x|
x.report("Dir[*]:") do
i = 0
n.times do
i = i + Dir["#{base_dir}*"].select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(*):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}/*").select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.entries():") do
i = 0
n.times do
i = i + Dir.entries(base_dir).select {|f| !File.directory? File.join(base_dir, f)}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir[**/*]:") do
i = 0
n.times do
i = i + Dir["#{base_dir}**/*"].select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(**/*):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}**/*").select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.entries() recursive walk:") do
i = 0
n.times do
def walk_dir(dir, result)
Dir.entries(dir).each do |file|
next if file == ".." || file == "."
path = File.join(dir, file)
if Dir.exist?(path)
walk_dir(path, result)
else
result << file
end
end
end
result = Array.new
walk_dir(base_dir, result)
i = i + result.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
x.report("Dir.glob(**/*, File::FNM_DOTMATCH):") do
i = 0
n.times do
i = i + Dir.glob("#{base_dir}**/*", File::FNM_DOTMATCH).select {|f| !File.directory? f}.length
end
puts " (#{i} files stepped over #{n} iterations)"
end
end
The differences in file counts are due to Dir.entries
including hidden files by default. Dir.entries
ended up taking a bit longer in this case due to needing to rebuild the absolute path of the file to determine if a file was a directory, but even without that it was still taking consistently longer than the other options in the recursive case. This was all using ruby 2.5.1 on OSX.

- 449
- 1
- 3
- 13
if you create directories with spaces:
mkdir "a b"
touch "a b/c"
You don't need to escape the directory names, it will do it automatically:
p Dir["a b/*"] # => ["a b/c"]

- 7,749
- 4
- 38
- 57