web-dev-qa-db-fra.com

Recherche dans un dossier et tous ses sous-dossiers de fichiers d'un certain type

J'essaie de rechercher tous les fichiers d'un type donné (par exemple .pdf) dans un dossier donné et de les copier dans un nouveau dossier. Ce que je dois être en mesure de faire est de spécifier un dossier racine et de rechercher dans ce dossier et tous ses sous-dossiers tous les fichiers qui correspondent au type donné (.pdf). Quelqu'un peut-il me donner un coup de main sur la façon dont je dois rechercher dans les sous-dossiers du dossier racine et leurs sous-dossiers, etc. Il semble qu'une méthode récursive ferait l'affaire ici, mais je ne peux pas l'implémenter correctement? (J'implémente ce programme dans Ruby soit dit en passant).

65
agentbanks217

Vous voulez le module Find . Find.find prend une chaîne contenant un chemin, et passera le chemin parent avec le chemin de chaque fichier et sous-répertoire à un bloc d'accompagnement. Un exemple de code:

require 'find'

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

Cela recherchera récursivement un chemin et stockera tous les noms de fichiers se terminant par .pdf dans un tableau.

60
jergason

Essaye ça:

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

ce qui est le même que

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

Où la variable de dossier est le chemin d'accès au dossier racine que vous souhaitez rechercher.

102
rogerdpack

Si la vitesse est un problème, préférez 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

Utilisation de Ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]

22
Dennis

Pour améliorer légèrement la réponse de Jergason et Matt ci-dessus, voici comment vous pouvez condenser en une seule ligne:

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

Cela utilise la méthode Find comme ci-dessus, mais exploite le fait que le résultat est un énumérable (et en tant que tel, nous pouvons utiliser select) pour récupérer un tableau avec l'ensemble des correspondances

11
chrisdurheim