Get names of all files from a folder with Ruby

RubyFileDirectoryFilenames

Ruby Problem Overview


I want to get all file names from a folder using Ruby.

Ruby Solutions


Solution 1 - Ruby

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"]

Solution 2 - Ruby

Dir.entries(folder)

example:

Dir.entries(".")

Source: http://ruby-doc.org/core/classes/Dir.html#method-c-entries

Solution 3 - Ruby

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) }

Solution 4 - Ruby

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?".

Solution 5 - Ruby

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

Solution 6 - Ruby

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"]

http://ruby-doc.org/core-2.5.0/Dir.html#method-c-children

Solution 7 - Ruby

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

Solution 8 - Ruby

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

Solution 9 - Ruby

this code returns only filenames with their extension (without a global path)

Dir.children("/path/to/search/")

Solution 10 - Ruby

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?('.')}

Solution 11 - Ruby

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().

Solution 12 - Ruby

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.

https://docs.ruby-lang.org/en/2.1.0/Rake/FileList.html

Solution 13 - Ruby

Dir.new('/home/user/foldername').each { |file| puts file }

Solution 14 - Ruby

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

Solution 15 - Ruby

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.

Solution 16 - Ruby

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.

Solution 17 - Ruby

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

Solution 18 - Ruby

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

Solution 19 - Ruby

In an IRB context, you can use the following to get the files in the current directory:

file_names = `ls`.split("\n")

You can make this work on other directories too:

file_names = `ls ~/Documents`.split("\n")

Solution 20 - Ruby

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"]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionŽeljko FilipinView Question on Stackoverflow
Solution 1 - RubyIan EcclesView Answer on Stackoverflow
Solution 2 - RubyŽeljko FilipinView Answer on Stackoverflow
Solution 3 - RubyEmiliano PoggiView Answer on Stackoverflow
Solution 4 - RubykonsoleboxView Answer on Stackoverflow
Solution 5 - Rubyuser1115652View Answer on Stackoverflow
Solution 6 - RubyMario Pérez AlarcónView Answer on Stackoverflow
Solution 7 - Rubymr.buttonsView Answer on Stackoverflow
Solution 8 - RubygilcierwebView Answer on Stackoverflow
Solution 9 - RubyИгорь ХлебниковView Answer on Stackoverflow
Solution 10 - RubyLahiru JayaratneView Answer on Stackoverflow
Solution 11 - Rubyyegor256View Answer on Stackoverflow
Solution 12 - RubyArturView Answer on Stackoverflow
Solution 13 - RubyAshwinView Answer on Stackoverflow
Solution 14 - RubySebastian CaponeView Answer on Stackoverflow
Solution 15 - RubyMikhail VasinView Answer on Stackoverflow
Solution 16 - RubyBen PennellView Answer on Stackoverflow
Solution 17 - RubyAndrewView Answer on Stackoverflow
Solution 18 - RubypunkstaView Answer on Stackoverflow
Solution 19 - RubyBalaji RadhakrishnanView Answer on Stackoverflow
Solution 20 - RubyDorianView Answer on Stackoverflow