Iterate through every file in one directory

RubyDirectoryFilesystems

Ruby Problem Overview


How do I write a loop in ruby so that I can execute a block of code on each file?

I'm new to ruby, and I've concluded that the way to do this is a do each loop.
The ruby file will be executed from a different directory than the directory I want to loop through.

I've tried the Dir.foreach and I couldn't get it to work.

Ruby Solutions


Solution 1 - Ruby

As others have said, Dir::foreach is a good option here. However, note that Dir::foreach and Dir::entries will always include . and .. (the current and parent directories). You will generally not want to work on them, so you can use Dir::each_child or Dir::children (as suggested by ma11hew28) or do something like this:

Dir.foreach('/path/to/dir') do |filename|
  next if filename == '.' or filename == '..'
  # Do work on the remaining files & directories
end

Dir::foreach and Dir::entries (as well as Dir::each_child and Dir::children) also include hidden files & directories. Often this is what you want, but if it isn't, you need to do something to skip over them.

Alternatively, you might want to look into Dir::glob which provides simple wildcard matching:

Dir.glob('/path/to/dir/*.rb') do |rb_filename|
  # Do work on files & directories ending in .rb
end

Solution 2 - Ruby

This is my favorite method for being easy to read:

Dir.glob("*/*.txt") do |my_text_file|
  puts "working on: #{my_text_file}..."
end

And you can even extend this to work on all files in subdirs:

Dir.glob("**/*.txt") do |my_text_file| # note one extra "*"
  puts "working on: #{my_text_file}..."
end

Solution 3 - Ruby

Dir has also shorter syntax to get an array of all files from directory:

Dir['dir/to/files/*'].each do |fname|
    # do something with fname
end

Solution 4 - Ruby

Dir.foreach("/home/mydir") do |fname|
  puts fname
end

Solution 5 - Ruby

The find library is designed for this task specifically: https://ruby-doc.org/stdlib-2.5.1/libdoc/find/rdoc/Find.html

require 'find'
Find.find(path) do |file|
  # process
end

This is a standard ruby library, so it should be available

Solution 6 - Ruby

To skip . & .., you can use Dir::each_child.

Dir.each_child('/path/to/dir') do |filename|
  puts filename
end

Dir::children returns an array of the filenames.

Solution 7 - Ruby

I like this one, that hasn't been mentioned above.

require 'pathname'

Pathname.new('/my/dir').children.each do |path|
    puts path
end

The benefit is that you get a Pathname object instead of a string, that you can do useful stuff with and traverse further.

Solution 8 - Ruby

Dir.new('/my/dir').each do |name|
  ...
end

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
QuestionAndrewView Question on Stackoverflow
Solution 1 - RubyTelemachusView Answer on Stackoverflow
Solution 2 - RubySimplGyView Answer on Stackoverflow
Solution 3 - RubywawkaView Answer on Stackoverflow
Solution 4 - RubyFredView Answer on Stackoverflow
Solution 5 - RubyFaisalView Answer on Stackoverflow
Solution 6 - Rubyma11hew28View Answer on Stackoverflow
Solution 7 - RubyskagedalView Answer on Stackoverflow
Solution 8 - RubyNick MooreView Answer on Stackoverflow