How to make Ruby's Find.find follow symlinks?

我的未来我决定 提交于 2019-12-08 15:51:50

问题


I have a file hierarchy and some of the sub-directories are relative symlinks. I am using Ruby's Find.find to crawl through these dirs and find some specific files. However it's not looking into any directory which is a symlink (it follows files which are symlinks).

Looking at the source code it seems the problem is because it's using File.lstat(file).directory? to test if something is a directory. This returns false for symlinks but File.stat.directory? returns true.

How can I make Find.find follow symlinks, short of monkey patching it to use File.stat instead of File.lstat?


回答1:


I came across the similar situation and decided to follow the real path without extra gem.

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

This way can't keep the original path with symbolic link but is fine for me at the moment.




回答2:


Use the file-find library by Daniel J. Berger. It's available as a Ruby gem. Then you can find recursively with:

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

NB: contrary to the documentation and intuition, setting :follow => false will actually make File::Find follow all symlinks, at least on my machine (Ubuntu 10.04, Ruby 1.8.7, file-find 0.3.4).

There is a bunch of other options available for File::Find, like name pattern, file type, atime, ctime, mtime, etc. Take a look at the RDoc.




回答3:


why not use Dir instead ? It follows symlinks Or you can try alib

To make Dir find files recursively, try double asterix Dir["**/*"]




回答4:


Wrote another option with loop checking and only limited recursion. Works with jruby as well.

Here's a gist: https://gist.github.com/akostadinov/05c2a976dc16ffee9cac




回答5:


For anyone else watching, I ended up using Pathname and the following recursive code:

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



回答6:


Here is a simpler and more efficient version of the recursive Pathname method:

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 


来源:https://stackoverflow.com/questions/3974087/how-to-make-rubys-find-find-follow-symlinks

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!