Как заставить Ruby Find.find следовать символическим ссылкам?

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

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

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

Ответ 1

Для тех, кто еще смотрит, я использовал 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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Ответ 6

Вот более простая и эффективная версия рекурсивного метода 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