Say you have a path String that can be one of:
And in each case, you wish to isolate the directory hierarchy within the String, using methods in the Ruby standard library, resulting in the value Foo/Bar
. Is there a single method that does this? Unfortunately, Path#cleanpath
and other methods in the API preserve the trailing slash in the String.
Is there a single method or short method chain that behaves like the following?
File.directory?(path) ? path.chomp("/") : File.split(path)[0]
Another example of the desired behavior via a regex, is here in this question .
No, there does not seem to be a way to do this explicitly in the Ruby API. The alternative is to use a regex, similar to what you see here .
Not quite sure if I understood your question, but if you want to split the directory and the file you could do like this:
path = "/etc/hosts" ; File.directory?(path) && [ File.dirname(path) + "/" +
File.basename(path), nil ] || [ File.dirname(path), File.basename(path) ]
=> ["/etc", "hosts"]
path = "/var/lib" ; File.directory?(path) && [ File.dirname(path) + "/" +
File.basename(path), nil ] || [ File.dirname(path), File.basename(path) ]
=> ["/var/lib", nil]
But note that this solutions applies only to the domain of existing files. If you are planning to create a path, it is impossible to know where Bar
should be placed in the answer (in the above example, it will be considered a file).
Note that the answer is supposed to be normalized:
path = "//etc//hosts" ; File.directory?(path) && [ File.dirname(path) + "/" +
File.basename(path), nil ] || [ File.dirname(path), File.basename(path) ]
=> ["/etc", "hosts"]
However the normalization of dirname
is limited/buggy (in my opinion):
path = "/./etc//hosts" ; File.directory?(path) && [ File.dirname(path) + "/"
+ File.basename(path), nil ] || [ File.dirname(path), File.basename(path) ]
=> ["/./etc", "hosts"]
Parsing is difficult and whenever possible to avoid it, you will certainly save time. Instead of normalizing file paths, I would rather trust their inode
number (again, valid only for the domain of existing files):
[ File.stat("/etc/hosts").ino , File.stat("/./etc/hosts").ino ]
=> [1309513, 1309513]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.