如何在Ruby中拆分目录字符串?

时间:2022-08-22 13:12:59

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]

4 个解决方案

#1


23  

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.

这适用于相对路径和非Unix平台,但是对于以“/”作为根目录开头的路径,那么你将获得一个空字符串作为数组中的第一个元素,我们想要“/ “相反。

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]

#2


35  

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

正确的答案是使用Ruby的Pathname(1.8.7以内的内置类,而不是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

资料来源:https://ruby-doc.org/stdlib-2.3.3/libdoc/pathname/rdoc/Pathname.html

#3


7  

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

Rake提供了一个添加到FileUtils的split_all方法。它非常简单,使用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:

rake版本与Rudd代码的输出略有不同。 Rake的版本忽略了多个斜杠:

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>

#4


2  

Warning: This solution is no longer the best one. See my other one.

警告:此解决方案不再是最佳解决方案。看到我的另一个。

Actually, there is a more neat solution. The main idea is to keep popping the basename until you are only left with the . or / .

实际上,有一个更简洁的解决方案。主要的想法是保持弹出基本名称,直到你只剩下。要么 / 。

def split_path(path)
    array = []
    until ['/', '.'].include? path
        array << File.basename(path)
        path = File.dirname(path)
    end
    array.reverse
end

split_path 'a/b/c/d' #=> ['a', 'b', 'c', 'd']

You can further build upon this idea, if you wish.

如果你愿意,你可以进一步发展这个想法。

#1


23  

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.

这适用于相对路径和非Unix平台,但是对于以“/”作为根目录开头的路径,那么你将获得一个空字符串作为数组中的第一个元素,我们想要“/ “相反。

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]

#2


35  

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

正确的答案是使用Ruby的Pathname(1.8.7以内的内置类,而不是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

资料来源:https://ruby-doc.org/stdlib-2.3.3/libdoc/pathname/rdoc/Pathname.html

#3


7  

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

Rake提供了一个添加到FileUtils的split_all方法。它非常简单,使用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:

rake版本与Rudd代码的输出略有不同。 Rake的版本忽略了多个斜杠:

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>

#4


2  

Warning: This solution is no longer the best one. See my other one.

警告:此解决方案不再是最佳解决方案。看到我的另一个。

Actually, there is a more neat solution. The main idea is to keep popping the basename until you are only left with the . or / .

实际上,有一个更简洁的解决方案。主要的想法是保持弹出基本名称,直到你只剩下。要么 / 。

def split_path(path)
    array = []
    until ['/', '.'].include? path
        array << File.basename(path)
        path = File.dirname(path)
    end
    array.reverse
end

split_path 'a/b/c/d' #=> ['a', 'b', 'c', 'd']

You can further build upon this idea, if you wish.

如果你愿意,你可以进一步发展这个想法。