Iterate through every file in one directory
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开发者_如何学JAVA through.I've tried the Dir.foreach
and I couldn't get it to work.
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
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
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
Dir.foreach("/home/mydir") do |fname|
puts fname
end
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
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.
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.
Dir.new('/my/dir').each do |name|
...
end
精彩评论