Как заставить 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["**/*"]
Ответ 5
Написал еще один вариант с проверкой цикла и только ограниченной рекурсией. Работает также с jruby.
Вот суть: https://gist.github.com/akostadinov/05c2a976dc16ffee9cac
Ответ 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