Как заставить Ruby's Find.find следовать символическим ссылкам? - PullRequest
9 голосов
/ 20 октября 2010

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

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

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

Ответы [ 6 ]

5 голосов
/ 02 декабря 2013

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

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 голосов
/ 14 апреля 2011

Используйте библиотеку поиска файлов Даниэля Дж. Бергера. Это доступно как рубиновый драгоценный камень. Тогда вы можете найти рекурсивно с:

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

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

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

1 голос
/ 09 сентября 2014

Написал еще один вариант с проверкой цикла и только ограниченной рекурсией. Работает также с jruby.

Вот суть: https://gist.github.com/akostadinov/05c2a976dc16ffee9cac

1 голос
/ 20 октября 2010

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

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

0 голосов
/ 06 июня 2017

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

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