Как открывать файлы относительно домашнего каталога

95

Следующее не работает Errno::ENOENT: No such file or directory, даже если файл существует:

open('~/some_file')

Однако я могу сделать это:

open(File.expand_path('~/some_file'))

У меня два вопроса:

  1. Почему openтильда не обрабатывается как указывающая на домашний каталог?
  2. Есть ли способ получше File.expand_path?
Питер
источник

Ответы:

109
  1. Оболочка (bash, zsh и т. Д.) Отвечает за расширение подстановочных знаков, поэтому в вашем первом примере нет оболочки, следовательно, нет расширения. Использование тильды для указания $HOME- простое соглашение; действительно, если вы посмотрите документацию File.expand_path, она правильно интерпретирует тильду, но это особенность самой функции, а не что-то присущее базовой системе; также File.expand_pathтребует $HOMEправильной установки переменной окружения. Что подводит нас к возможной альтернативе ...
  2. Попробуй это:

    open(ENV['HOME']+'/some_file')

Надеюсь, это достаточно гладко. Я лично считаю, что использование переменной окружения семантически проще, чем использование expand_path.

Roadmaster
источник
с помощью окон ... пришлось сделатьopen(ENV['HOME']+'some_file')
Дэвид Вест
9
Используйте просто, File.join(ENV['HOME'], '/some_file')чтобы он работал в обоих случаях.
Марчин Билски
123

Не уверен, было ли это доступно до Ruby 1.9.3, но я считаю, что наиболее элегантным решением является использование того, Dir.homeчто является частью ядра.

open("#{Dir.home}/some_file")
аллесклар
источник
2
Нет, недоступно для пользователей ниже 1.9.3 ( apidock.com/ruby/v1_9_2_180/Dir/home/class ).
Ян Воган
12

Вместо того, чтобы полагаться на $HOMEправильную установку переменной среды, что может быть проблемой при использовании компьютеров в общей сети для разработки, вы можете получить это из Ruby, используя:

require 'etc'
open ("#{Etc.getpwuid.dir}/some_file")

Я считаю, что это идентифицирует текущего пользователя, вошедшего в систему, и получает его домашний каталог, а не полагается на $HOMEзаданную глобальную переменную среды. Я считаю, что это альтернативное решение вышеупомянутому.

Voke Ransom Anighoro
источник
2

Я обнаружил проблему с тильдой, и был создан патч для добавления, absolute_path который рассматривает тильду как обычный символ.

Из файловой документации:

absolute_path(file_name [, dir_string] )  abs_file_name

Преобразует путь в абсолютный путь. Относительные пути ссылаются на текущий рабочий каталог процесса, если не указана dir_string, и в этом случае он будет использоваться в качестве начальной точки. Если указанный путь начинается с символа «~», он НЕ раскрывается, он рассматривается как обычное имя каталога.

Чарльз Эдвард Торнтон
источник