2010-08-17 24 views
56

Estoy tratando de buscar todos los archivos de un tipo determinado (por ejemplo, .pdf) en una carpeta determinada y copiarlos en una carpeta nueva. Lo que necesito hacer es especificar una carpeta raíz y buscar en esa carpeta y todas sus subcarpetas los archivos que coincidan con el tipo dado (.pdf). ¿Alguien puede darme una explicación sobre cómo debo buscar a través de las subcarpetas de la carpeta raíz y sus subcarpetas y demás? Parece que un método recursivo sería el truco aquí, pero no puedo implementar uno correctamente? (Estoy implementando este programa en ruby ​​por cierto).Buscar en una carpeta y en todas sus subcarpetas archivos de cierto tipo

Respuesta

54

Desea el módulo Find. Find.find toma una cadena que contiene una ruta, y pasará la ruta principal junto con la ruta de acceso de cada archivo y subdirectorio a un bloque acompañante. Un código de ejemplo:

require 'find' 

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

que la voluntad de forma recursiva buscar un camino, y almacenar todos los nombres de los archivos que terminan en .pdf en una matriz.

79

Prueba esto:

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

que es el mismo que

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

donde la variable carpeta es la ruta a la carpeta raíz de que deseas buscar.

+0

El enfoque es correcto, pero la aplicación es incorrecto. Necesita ser Dir.glob ('**/*. Pdf') – jergason

+2

Creo que el OP quería recursivo, ¿verdad? – rogerdpack

+0

La respuesta original (rogerdpack) funcionó para mí, pero la de Jergason no, me temo. – Joyce

9

Como una pequeña mejora a Jergason y de Matt respuesta anterior, aquí es cómo se puede condensar a una sola línea:

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

Esto utiliza el método Find que el anterior, pero aprovecha el hecho de que el resultado es un enumerable (y como tal podemos usar seleccionar) para obtener una matriz de nuevo con el conjunto de coincidencias

16

Si la velocidad es una preocupación, prefiera Dir.glob sobre 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 

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

+2

Gracias por la publicación. Es muy útil para principiantes como yo averiguar qué método debo usar entre 'Dir.glob' vs' Find.find'. – itsh

+2

Buscar debería ser más lento en este caso porque está encontrando con una expresión regular. Dir.glob, por otro lado, no es tan poderoso como una expresión regular, así que espero que sea más rápido. – hirowatari

Cuestiones relacionadas