После symlinking файла, как мне получить путь к исходному файлу в Ruby?

У меня есть Ruby script с контуром /foo/bar/gazook/script.rb. Я также создал символическую ссылку на него в $HOME/bin.

Теперь я хочу, чтобы мой Ruby script получил доступ к другому файлу в каталоге /foo, и чтобы относительные пути относились, у меня есть переменная FOO_DIRECTORY = File.expand_path(File.dirname(__FILE__) + "/../../") в моем script.

Проблема в том, что если я запустил свой script из своей символической ссылки, этот относительный каталог ошибочен (так как я предполагаю, что он расширяется из другого места).

Как это исправить? Есть ли способ, кроме использования абсолютного пути?

Ответы

Ответ 1

Вы можете использовать File.readlink, чтобы разрешить символическую ссылку, но вы хотите проверить File.symlink?.

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

Затем вы можете работать с path вместо __FILE__. Возможно, вы захотите использовать $0 вместо __FILE__, __FILE__ - это текущее имя файла, тогда как $0 - это имя текущего script.

Ответ 2

Чтобы получить какой-либо путь относительно местоположения вашего script, всегда используйте __dir__.

__dir__ - это сжатый способ сказать File.dirname(File.realpath(__FILE__)). Он доступен в Ruby >= 2.0. В __dir__.

File.realpath(__FILE__) (или Pathname#realpath) имеет три преимущества по сравнению с File.readlink:

  • Он расширяет символические ссылки в любом месте пути. readlink только расширяет пути, которые являются последней частью аргумента.
  • Он (рекурсивно) разрешает символические ссылки на символические ссылки на... readlink разрешает только первый уровень.
  • Вам не нужно проверять, является ли path символической ссылкой вообще. Таким образом, вы можете отказаться от if File.symlink?.

Следовательно, было бы полезно использовать FOO_DIRECTORY = File.join(__dir__, '..', '..') или FOO_DIRECTORY = File.dirname(File.dirname(__dir__))

Ответ 3

Попробуйте это

require 'pathname'
p File.dirname(Pathname.new(__FILE__).realpath)

Ответ 4

Попробуйте следующее:

FOO_DIRECTORY = File.expand_path("../../../", __FILE__)

Я говорю, что проблема в том, что ваш файл symlink интерпретирует File.dirname(__FILE__)