Reputation: 18594
It's very strange, I cannot find any standard way with Ruby to copy a directory recursively while dereferencing symbolic links. The best I could find is FindUtils.cp_r
but it only supports dereferencing the root src directory.
copy_entry
is the same although documentation falsely shows that it has an option dereference
. In source it is dereference_root
and it does only that.
Also I can't find a standard way to recurse into directories. If nothing good exists, I can write something myself but wanted something simple and tested to be portable across Windows and Unix.
Upvotes: 0
Views: 675
Reputation: 18594
Here's my implementation of find -follow
in ruby:
https://gist.github.com/akostadinov/05c2a976dc16ffee9cac
I could have isolated it into a class or monkey patch Find but I decided to do it as a self-contained method. There might be room for improvement because it doesn't work with jruby. If anybody has an idea, it will be welcome.
Update: found out why not working with jruby - https://github.com/jruby/jruby/issues/1895
I'll try to workaround. I implemented a workaround.
Update 2: now cp_r_dereference
method ready - https://gist.github.com/akostadinov/fc688feba7669a4eb784
Upvotes: 0
Reputation: 160551
The standard way to recurse into directories is to use the Find class but I think you're going to have to write something. The built-in FileUtils methods are building blocks for normal operations but your need is not normal.
I'd recommend looking at the Pathname class which comes with Ruby. It makes it easy to walk directories using find
, look at the type of the file and dereference it if necessary. In particular symlink?
will tell you if a file is a soft-link and realpath
will resolve the link and return the path to the real file.
For instance I have a soft-link in my home directory from .vim
to vim
:
vim = Pathname.new ENV['HOME'] + '/.vim'
=> #<Pathname:/Users/ttm/.vim>
vim.realpath
=> #<Pathname:/Users/ttm/vim>
Pathname is quite powerful, and I found it very nice when having to do some major directory traversals and working with soft-links. The docs say:
The goal of this class is to manipulate file path information in a neater way than standard Ruby provides. [...]
All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
If you use find
, you'll probably want to implement the prune
method which is used to skip entries you don't want to recurse into. I couldn't find it in Pathname when I was writing code so I added it using something like:
class Pathname
def prune
Find.prune
end
end
Upvotes: 2