После 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__)