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

And*_*imm 20 ruby linux windows string

在红宝石中,我能够做到

File.dirname("/home/gumby/bigproject/now_with_bugs_fixed/32/FOO_BAR_2096.results")
Run Code Online (Sandbox Code Playgroud)

得到

"/home/gumby/bigproject/now_with_bugs_fixed/32"
Run Code Online (Sandbox Code Playgroud)

但现在我想将该目录字符串拆分为单个文件夹组件,例如

["home", "gumby", "bigproject", "now_with_bugs_fixed", "32"]
Run Code Online (Sandbox Code Playgroud)

除了使用之外,有没有办法做到这一点

directory.split("/")[1:-1]
Run Code Online (Sandbox Code Playgroud)

Rok*_*alj 37

正确的答案是使用Ruby Pathname(自1.8.7以来的内置类,而不是gem).

看代码:

require 'pathname'

def split_path(path)
    Pathname(path).each_filename.to_a
end
Run Code Online (Sandbox Code Playgroud)

执行此操作将丢弃路径是绝对路径还是相对路径的信息.要检测到这一点,您可以调用absolute?方法Pathname.

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


Rud*_*ski 24

没有内置函数可以将路径拆分到其组件目录中,就像要加入它们一样,但是您可以尝试以跨平台方式伪造它:

directory_string.split(File::SEPARATOR)
Run Code Online (Sandbox Code Playgroud)

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

directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}
Run Code Online (Sandbox Code Playgroud)

如果您只想要像上面提到的那样没有根目录的目录,那么您可以将其更改为从第一个元素中选择.

directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}[1..-1]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在Windows上,File :: SEPERATOR是/,而不是\.因此,如果你只对File.join的结果使用该方法,它将正常工作,但如果你想使用用户输入或其他可以使用\作为文件分隔符的源,你应该做一些像`dir.split( Regexp.union(*[File :: SEPARATOR,File :: ALT_SEPARATOR] .compact))`(或更可读的版本) (5认同)
  • 抱歉垃圾邮件,但这个解决方案无可争议地更好:http://stackoverflow.com/a/21572944/924109 (5认同)

Jam*_*ore 7

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

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>