How to open files relative to home directory
The following fails with Errno::ENOENT: No such file or directory
, even if the file exists:
open('~/some_file')
However, I can do this:
open(File.expand_path('~/some_file'))
I have two questions:
- Why doesn't
open
process the tilde as pointing to开发者_JAVA技巧 the home directory? - Is there a slicker way than
File.expand_path
?
Not sure if this was available before Ruby 1.9.3 but I find that the most elegant solution is to use Dir.home
which is part of core.
open("#{Dir.home}/some_file")
- The shell (bash, zsh, etc) is responsible for wildcard expansion, so in your first example there's no shell, hence no expansion. Using the tilde to point to
$HOME
is a mere convention; indeed, if you look at the documentation forFile.expand_path
, it correctly interprets the tilde, but it's a feature of the function itself, not something inherent to the underlying system; also,File.expand_path
requires the$HOME
environment variable to be correctly set. Which bring us to the possible alternative... Try this:
open(ENV['HOME']+'/some_file')
I hope it's slick enough. I personally think using an environment variable is semantically clearer than using expand_path
.
Instead of relying on the $HOME
environment variable being set correctly, which could be a hassle when you use shared network computers for development, you could get this from Ruby using:
require 'etc'
open ("#{Etc.getpwuid.dir}/some_file")
I believe this identifies the current logged-in user and gets their home directory rather than relying on the global $HOME
environment variable being set. This is an alternative solution to the above I reckon.
I discovered the tilde problem, and a patch was created to add absolute_path
which treats tilde as an ordinary character.
From the File documentation:
absolute_path(file_name [, dir_string] ) → abs_file_name
Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless dir_string is given, in which case it will be used as the starting point. If the given pathname starts with a “~” it is NOT expanded, it is treated as a normal directory name.
精彩评论