it-swarm.dev

Поиск в папке и во всех ее подпапках файлов определенного типа

Я пытаюсь найти все файлы определенного типа (скажем, .pdf) в заданной папке и скопировать их в новую папку. Что мне нужно сделать, это указать корневую папку и выполнить поиск в этой папке и во всех ее подпапках любых файлов, соответствующих данному типу (.pdf). Может кто-нибудь подсказать мне, как мне искать в подпапках корневой папки, их подпапках и так далее. Звучит так, будто рекурсивный метод справился бы с задачей, но я не могу правильно ее реализовать? (Кстати, я реализую эту программу в Ruby).

65
agentbanks217

Вы хотите модуль Найти . Find.find принимает строку, содержащую путь, и передает родительский путь вместе с путем к каждому файлу и подкаталогу в сопровождающий блок. Пример кода:

require 'find'

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

Это будет рекурсивно искать путь и сохранять все имена файлов, заканчивающиеся на .pdf, в массиве.

60
jergason

Попробуй это:

Dir.glob("#{folder}/**/*.pdf")

который так же, как

Dir["#{folder}/**/*.pdf"]

Где переменная папки - это путь к корневой папке, по которой вы хотите выполнить поиск.

102
rogerdpack

Если важна скорость, предпочтите 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

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

Использование Ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]

21
Dennis

В качестве небольшого улучшения ответа Джергасона и Мэтта выше, вот как вы можете сжать одну строку:

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

При этом используется метод Find, как указано выше, но используется тот факт, что результат является перечисляемым (и поэтому мы можем использовать select), чтобы вернуть массив с набором совпадений.

11
chrisdurheim