在文件夹及其所有子文件夹中搜索特定类型的文件

age*_*217 65 ruby recursion file-io

我试图在给定文件夹中搜索给定类型的所有文件(例如.pdf)并将它们复制到新文件夹.我需要做的是指定一个根文件夹,并在该文件夹及其所有子文件夹中搜索与给定类型(.pdf)匹配的任何文件.任何人都可以告诉我如何搜索根文件夹的子文件夹及其子文件夹等.这听起来像一个递归方法可以解决这个问题,但我无法正确实现一个?(顺便说一下,我正在ruby中实现这个程序).

rog*_*ack 104

试试这个:

Dir.glob("#{folder}/**/*.pdf")
Run Code Online (Sandbox Code Playgroud)

这是一样的

Dir["#{folder}/**/*.pdf"]
Run Code Online (Sandbox Code Playgroud)

其中folder变量是要搜索的根文件夹的路径.

  • 我更喜欢这个,没有额外的要求更少的代码 (6认同)
  • 我认为OP想要递归,不是吗? (3认同)
  • @rogerdpack据我所知,这个方法是递归的.答案实际应该是`Dir.glob("#{folder}/**/*.pdf")`,其中`folder`变量是要搜索的根文件夹的路径. (2认同)
  • @Konstantin 这个,或者`Dir#[]`,是我通常使用的。但是,有一个问题:`Dir.glob` 将所有路径加载到内存中。这通常很好,但是如果您有大量路径,人们可能更喜欢使用 Find 模块,因为它会在找到路径时将路径传递给块。 (2认同)
  • 我同意@WayneConrad 的观点。由于 Ruby 分配了足够的内存来存储大数组,因此您可能会无意中停止程序。这与[slurping a file](/sf/ask/1763248371/)非常相似。让“Find”处理层次结构比将其扔到操作系统并可能得到意外的数组更有效,而且可能更快。调试这种情况很困难。 (2认同)

jer*_*son 61

你想要Find模块.Find.find获取包含路径的字符串,并将父路径以及每个文件和子目录的路径传递给随附的块.一些示例代码:

require 'find'

pdf_file_paths = []
Find.find('path/to/search') do |path|
  pdf_file_paths << path if path =~ /.*\.pdf$/
end
Run Code Online (Sandbox Code Playgroud)

这将递归搜索路径,并将以.pdf结尾的所有文件名存储在一个数组中.


Den*_*nis 22

如果速度是一个问题,宁愿Dir.glob结束Find.find.

Warming up --------------------------------------
           Find.find   124.000  i/100ms
            Dir.glob   515.000  i/100ms
Calculating -------------------------------------
           Find.find      1.242k (± 4.7%) i/s -      6.200k in   5.001398s
            Dir.glob      5.249k (± 4.5%) i/s -     26.265k in   5.014632s

Comparison:
            Dir.glob:     5248.5 i/s
           Find.find:     1242.4 i/s - 4.22x slower
Run Code Online (Sandbox Code Playgroud)

 

require 'find'
require 'benchmark/ips'

dir = '.'

Benchmark.ips do |x|
  x.report 'Find.find' do
    Find.find(dir).select { |f| f =~ /\*\.pdf/ }
  end

  x.report 'Dir.glob' do
    Dir.glob("#{dir}/**/*\.pdf")
  end

  x.compare!
end
Run Code Online (Sandbox Code Playgroud)

运用 ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]

  • 在这种情况下,查找应该更慢,因为您正在查找正则表达式.另一方面,Dir.glob并不像正则表达式那么强大,所以我希望它更快. (4认同)
  • 谢谢你的帖子.对于像我这样的初学者来说,找出`Dir.glob` vs`Find.find`中应该使用哪种方法非常有用. (2认同)

chr*_*eim 11

作为Jergason和Matt上面的答案的一个小改进,这里是你如何凝聚成一条线:

pdf_file_paths = Find.find('path/to/search').select { |p| /.*\.pdf$/ =~ p }
Run Code Online (Sandbox Code Playgroud)

这使用了上面的Find方法,但是利用了结果是可枚举的事实(因此我们可以使用select)来获取带有匹配集的数组