Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split a directory string in Ruby?

In ruby, I'm able to do

File.dirname("/home/gumby/bigproject/now_with_bugs_fixed/32/FOO_BAR_2096.results")

and get

"/home/gumby/bigproject/now_with_bugs_fixed/32"

but now I'd like to split up that directory string into the individual folder components, ie something like

["home", "gumby", "bigproject", "now_with_bugs_fixed", "32"]

Is there a way to do that other than using

directory.split("/")[1:-1]
like image 962
Andrew Grimm Avatar asked Sep 03 '09 01:09

Andrew Grimm


3 Answers

The correct answer is to use Ruby's Pathname (in-built class since 1.8.7, not a gem).

See the code:

require 'pathname'

def split_path(path)
    Pathname(path).each_filename.to_a
end

Doing this will discard the information whether the path was absolute or relative. To detect this, you can call absolute? method on Pathname.

Source: https://ruby-doc.org/stdlib-2.3.3/libdoc/pathname/rdoc/Pathname.html

like image 185
Rok Kralj Avatar answered Nov 02 '22 11:11

Rok Kralj


There's no built-in function to split a path into its component directories like there is to join them, but you can try to fake it in a cross-platform way:

directory_string.split(File::SEPARATOR)

This works with relative paths and on non-Unix platforms, but for a path that starts with "/" as the root directory, then you'll get an empty string as your first element in the array, and we'd want "/" instead.

directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}

If you want just the directories without the root directory like you mentioned above, then you can change it to select from the first element on.

directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}[1..-1]
like image 26
Rudd Zwolinski Avatar answered Nov 02 '22 12:11

Rudd Zwolinski


Rake provides a split_all method added to FileUtils. It's pretty simple and uses File.split:

def split_all(path)
  head, tail = File.split(path)
  return [tail] if head == '.' || tail == '/'
  return [head, tail] if head == '/'
  return split_all(head) + [tail]
end

taken from rake-0.9.2/lib/rake/file_utils.rb

The rake version has slightly different output from Rudd's code. Rake's version ignores multiple slashes:

irb(main):014:0> directory_string = "/foo/bar///../fn"
=> "/foo/bar///../fn"
irb(main):015:0> directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}[1..-1]
=> ["foo", "bar", "/", "/", "..", "fn"]
irb(main):016:0> split_all directory_string
=> ["/", "foo", "bar", "..", "fn"]
irb(main):017:0>
like image 7
James Moore Avatar answered Nov 02 '22 10:11

James Moore