2010-10-20 5 views
8

У меня есть иерархия файлов, а некоторые из подкаталогов - относительные символические ссылки. Я использую Ruby's Find.find, чтобы просканировать эти файлы и найти определенные файлы. Однако он не ищет в какой-либо директории, которая является символической ссылкой (она следует за файлами, которые являются символическими ссылками).Как заставить Ruby Find.find следовать символическим ссылкам?

Если вы ищете source code, то проблема заключается в том, что он использует File.lstat(file).directory?, чтобы проверить, что-то является каталогом. Это возвращает false для символических ссылок, но File.stat.directory? возвращает true.

Как я могу сделать Find.find следовать символическим ссылкам, кроме обезьяны, исправляя его, чтобы использовать File.stat вместо File.lstat?

ответ

0

Для любого другого наблюдения, я закончил с использованием Pathname и следующий рекурсивный код:

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

Почему бы не использовать Dir? Из этого следует симлинки Или вы можете попробовать alib

Чтобы Dir найти файлы рекурсивно, попробуйте дважды Астерикс Dir["**/*"]

+0

Как сделать 'Dir' найти файлы рекурсивно? Я не вижу метода в классе Dir - я что-то пропустил? – arnab

+0

В то время как у «alib», похоже, есть похожий код, я никогда не слышал об этом - это не на github/gemcutter, а само имя (это действительно «lib») не внушает большого доверия. Вы использовали его в производственном коде? Как прошел опыт? – arnab

+0

Dir ["**/*"], похоже, работает только для одного уровня иерархии - у меня было несколько уровней, причем некоторые из них были символическими. Я закончил использование Pathname # children (http://ruby-doc.org/core/classes/Pathname.html#M001721) – arnab

3

Используйте библиотеку файлов, найти на Daniel J. Berger. Он доступен как драгоценный камень Ruby. Тогда вы можете найти рекурсивно:

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

NB: вопреки документации и интуиции, установка: следовать => ложь будет на самом деле сделать File :: Find следуют все символические ссылки, по крайней мере, на моей машине (Ubuntu 10.04, Ruby 1.8.7, поиск файла 0.3.4).

Существует множество других опций, доступных для File :: Find, таких как шаблон имени, тип файла, atime, ctime, mtime и т. Д. Взгляните на RDoc.

+0

Спасибо. В итоге я использовал Pathname с рекурсивной функцией. Я попробую это в следующий раз, когда я нахожусь в этой кодовой базе (мой вопрос был с октября 2010 года). – arnab

5

я наткнулся на подобную ситуацию и решил последовать реальный путь без дополнительного драгоценного камня.

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") 

Этот способ не может содержать исходный путь с символической ссылкой, но в данный момент он подходит для меня.

0

Вот более простой и эффективный вариант рекурсивного метода PathName:

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 
Смежные вопросы