遍历一个目录中的每个文件
Posted
技术标签:
【中文标题】遍历一个目录中的每个文件【英文标题】:Iterate through every file in one directory 【发布时间】:2011-01-31 12:28:23 【问题描述】:如何在 ruby 中编写一个循环,以便在每个文件上执行一段代码?
我是 ruby 新手,我得出的结论是这样做的方法是每个循环。 ruby 文件将从与我要循环的目录不同的目录中执行。
我尝试了Dir.foreach
,但无法正常工作。
【问题讨论】:
你能具体说明当你试图让它工作时发生了什么吗?您尝试了哪些确切的代码(或相关的块,如果它很长)?您收到了哪些错误消息?Dir.foreach
用于迭代目录的内容,所以还有很多事情要做。
如果您只想要目录中的文件,请不要忘记在遍历目录内容时测试文件:do_something_with(entry) if File.file?(entry)
使用'img/*.jpg,png,gif,jpeg'
抓取多个扩展。
不幸的是,@ChrisPeters 似乎不太可能,因为 OP 已经四年多没有出现在该网站上了。
【参考方案1】:
正如其他人所说,Dir::foreach
是一个不错的选择。但是,请注意Dir::foreach
和Dir::entries
将始终包括.
和..
(当前目录和父目录)。您通常不想处理它们,因此您可以使用Dir::each_child
或Dir::children
(如suggested by ma11hew28)或执行以下操作:
Dir.foreach('/path/to/dir') do |filename|
next if filename == '.' or filename == '..'
# Do work on the remaining files & directories
end
Dir::foreach
和 Dir::entries
(以及 Dir::each_child
和 Dir::children
)还包括隐藏文件和目录。通常这是您想要的,但如果不是,您需要做一些事情来跳过它们。
或者,您可能想查看Dir::glob
,它提供了简单的通配符匹配:
Dir.glob('/path/to/dir/*.rb') do |rb_filename|
# Do work on files & directories ending in .rb
end
【讨论】:
如果目录包含大量文件,请使用Dir.foreach
!
谢谢!让它变得更好的小模组:next if File.directory? item
@mr.buttons 这并不总是正确的。有时人们希望处理目录 以及文件。我给出了避免 .
或 ..
的特殊列表的代码,因为人们几乎总是想忽略这两个。
@Tilo:只是出于兴趣,想详细解释一下为什么? :)
@mkataja Dir.foreach
迭代而不是在前面建立一个(可能很大的)数组(Dir.glob
确实如此)。因此,如果目录真的很大,它会产生性能差异。在正常情况下您不会注意到,但在压力条件下,这绝对很重要。【参考方案2】:
要跳过.
和..
,您可以使用Dir::each_child
。
Dir.each_child('/path/to/dir') do |filename|
puts filename
end
Dir::children
返回文件名数组。
【讨论】:
【参考方案3】:find 库是专门为这个任务设计的: https://ruby-doc.org/stdlib-2.5.1/libdoc/find/rdoc/Find.html
require 'find'
Find.find(path) do |file|
# process
end
这是一个标准的 ruby 库,所以它应该是可用的
【讨论】:
File.find
尽可能递归地向下,从你给它的任何路径开始。我不确定这是 OP 想要的。
我似乎无法使用该方法 - Find.find ?我是否需要下载包含此功能的库?
@user470184:“Find”是一个标准的 ruby 库,应该在默认的 ruby 安装中可用。但是,您需要“要求 'find'”才能使用它。
@Faisal 我可以将像*.rb
这样的全局模式传递给find()
【参考方案4】:
我喜欢这个,上面没有提到。
require 'pathname'
Pathname.new('/my/dir').children.each do |path|
puts path
end
好处是你得到一个路径名对象而不是一个字符串,你可以用它做有用的东西并进一步遍历。
【讨论】:
【参考方案5】:Dir 还有更短的语法来从目录中获取所有文件的数组:
Dir['dir/to/files/*'].each do |fname|
# do something with fname
end
【讨论】:
这段代码中的什么阻止了目录也被fname
的迭代使用?【参考方案6】:
这是我最喜欢的易于阅读的方法:
Dir.glob("*/*.txt") do |my_text_file|
puts "working on: #my_text_file..."
end
你甚至可以扩展它来处理子目录中的所有文件:
Dir.glob("**/*.txt") do |my_text_file| # note one extra "*"
puts "working on: #my_text_file..."
end
【讨论】:
【参考方案7】:Dir.new('/my/dir').each do |name|
...
end
【讨论】:
除了 Dir.new('/my/dir') 还有 Dir.entries('/my/dir') 但 Dir.foreach() 更简洁一些。 @Z.E.D.同样Dir.foreach
迭代,而Dir.entries
一次构建整个数组。因此,如果目录很大,则内存不足。 (通常没什么大不了的,可能,但仍然......)【参考方案8】:
Dir.foreach("/home/mydir") do |fname|
puts fname
end
【讨论】:
或者使用 Dir#[] 或 Dir#glob以上是关于遍历一个目录中的每个文件的主要内容,如果未能解决你的问题,请参考以下文章