Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After symlinking a file, how do I get the path of the original file in Ruby?

Tags:

ruby

symlink

I have a Ruby script with path /foo/bar/gazook/script.rb. I also created a symlink to it in $HOME/bin.

Now, I want my Ruby script to access some other file in directory /foo, and to keep paths relative, I have a variable FOO_DIRECTORY = File.expand_path(File.dirname(__FILE__) + "/../../") in my script.

The problem is that if I run my script from its symlink, this relative directory is wrong (since I guess its expanding from a different location).

How do I fix this? Is there a way besides using an absolute path?

like image 983
grautur Avatar asked Dec 16 '11 19:12

grautur


2 Answers

You can use File.readlink to resolve a symlink but you'll want to check File.symlink? first.

path = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__

Then you can work with path instead of __FILE__. You might want to use $0 instead of __FILE__ as well, __FILE__ is the current filename whereas $0 is the name of the current script.

like image 108
mu is too short Avatar answered Oct 15 '22 22:10

mu is too short


To get any path relative to the location of your script, always use __dir__.

__dir__ is a concise way of saying File.dirname(File.realpath(__FILE__)). It's available in Ruby >= 2.0. On __dir__.

File.realpath(__FILE__) (or Pathname#realpath) has three advantages compared to File.readlink:

  • It expands symlinks anywhere in the path. readlink only expands paths that are the last part of the argument.
  • It (recursively) resolves symlinks to symlinks to... readlink resolves only the first level.
  • You do not have to check whether path is a symlink at all. Thus you can drop the if File.symlink?.

Consequently it would be good to use FOO_DIRECTORY = File.join(__dir__, '..', '..') or FOO_DIRECTORY = File.dirname(File.dirname(__dir__))

like image 34
hagello Avatar answered Oct 15 '22 21:10

hagello