2010-10-20 14 views
8

que tienen una jerarquía de archivos y algunos de los subdirectorios son enlaces simbólicos relativos. Estoy usando Ruby's Find.find para rastrear estos directorios y encontrar algunos archivos específicos. Sin embargo, no busca en ningún directorio que sea un enlace simbólico (sigue a los archivos que son enlaces simbólicos).¿Cómo hacer que Find.find de Ruby siga los enlaces simbólicos?

Al mirar source code parece que el problema es porque está usando File.lstat(file).directory? para probar si algo es un directorio. Esto devuelve false para enlaces pero File.stat.directory? vuelve true.

¿Cómo puedo hacer que Find.find sigan los enlaces simbólicos, sin monkey al parchearlo para usar File.stat en lugar de File.lstat?

Respuesta

0

Para cualquier observación de los demás, que terminé usando Pathname y el siguiente código recursivo:

def all_files_under(*paths) 
    paths.flatten! 
    paths.map! { |p| Pathname.new(p) } 
    files = paths.select { |p| p.file? } 
    (paths - files).each do |dir| 
    files << all_files_under(dir.children) 
    end 
    files.flatten 
end 
1

por qué no usar Dir en su lugar? De ello se sigue enlaces simbólicos o puede probar alib

Para hacer Dir encuentran los archivos de forma recursiva, tratan doble asterisco Dir["**/*"]

+0

¿Cómo hago 'Dir' encontrar archivos de forma recursiva? No veo un método en la clase Dir. ¿Me falta algo aquí? Mientras – arnab

+0

"alib" parece tener un código similar, que nunca han oído hablar de él - no es en github/tallador de gemas y el propio nombre (¿es realmente "un lib") no inspira mucha confianza. ¿Lo has usado en el código de producción? ¿Cómo estuvo la experiencia? – arnab

+0

Dir [ "**/*"] parece que funciona sólo para un nivel de jerarquía - que tenía múltiples niveles, con algunos de ellos como enlaces simbólicos. Terminé usando rutas de directorios Menores (http://ruby-doc.org/core/classes/Pathname.html#M001721) – arnab

3

utilizar la biblioteca de archivos encuentra por Daniel J. Berger. Está disponible como una gema Ruby. A continuación, se puede encontrar de forma recursiva con:

require 'rubygems' 
require 'file/find' 
File::Find.new(:follow => false).find { |p| puts p } 

NB: al contrario de la documentación y la intuición, el establecimiento de: seguir => false hará realmente Archivo :: Buscar seguir todos los enlaces simbólicos, al menos en mi máquina (Ubuntu 10.04, Rubí 1.8.7, archivo-find 0.3.4).

Hay un montón de otras opciones disponibles para File :: Encuentra, como patrón de nombre, tipo de archivo, atime, ctime, -mtime, etc. Tome un vistazo a la RDoc.

+0

Gracias. Terminé usando Pathname con una función recursiva para hacer esto. Probaré esto la próxima vez que esté en esa base de código (mi pregunta era de octubre de 2010). – arnab

5

me encontré con la situación similar y decidió seguir el camino real sin joya adicional.

require 'find' 

paths = ARGV 

search_dirs = paths.dup 
found_files = Array.new 

until search_dirs.size == 0 
    Find.find(search_dirs.shift) do |path| 
    if File.directory?(path) && File.symlink?(path) 
     search_dirs << File.realdirpath(path) 
    else 
     found_files << path 
    end 
    end 
end 

puts found_files.join("\n") 

De esta manera no se puede mantener la ruta original con enlace simbólico, pero está muy bien para mí en este momento.

0

Aquí es una versión más simple y más eficiente del método del nombre de ruta recursiva:

def find_files(*paths) 
    paths.flatten.map do |path| 
    path = Pathname.new(path) 
    path.file? ? [path.to_s] : find_files(path.children) 
    end.flatten 
end 
Cuestiones relacionadas