2009-09-03 47 views
17

在Ruby中,我能夠做如何在Ruby中拆分目錄字符串?

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

,並得到

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

,但現在我想該目錄字符串分割成單獨的文件夾中的組件,即像

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

有沒有辦法做到這一點以外使用

directory.split("/")[1:-1] 

回答

22

有沒有內置的功能好像有加入他們分裂的路徑成組成目錄,但你可以嘗試假了在跨平臺的方式:

directory_string.split(File::SEPARATOR) 

這適用於相對路徑和非Unix平臺上,但對於以"/"作爲根目錄開始的路徑,則會獲得一個空字符串作爲數組中的第一個元素,而我們希望改爲"/"

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

如果你想不只是根目錄下的目錄,如你上面提到的,那麼你可以改變它從第一個元素進行選擇。

directory_string.split(File::SEPARATOR).map {|x| x=="" ? File::SEPARATOR : x}[1..-1] 
+5

請注意,在Windows文件:: SEPERATOR是/,而不是\。所以如果你只在File.join的結果中使用這種方法,它將會正常工作,但是如果你想使用用戶輸入或其他可以使用\作爲文件分隔符的源文件,你應該像'dir.split(正則表達式。union(* [File :: SEPARATOR,File :: ALT_SEPARATOR] .compact))(或更可讀的版本) – sepp2k 2009-09-03 09:37:02

+5

對不起,垃圾郵件,但這種解決方案是無可爭議的更好:http://stackoverflow.com/a/ 21572944/924109 – 2014-02-06 13:02:20

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> 
2

警告:此解決方案不再是最好的解決方案。看到我的另一個。

實際上,還有一個更加整潔的解決方案。主要想法是繼續彈出基名,直到只剩下./

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'] 

如果您願意,您可以進一步構建這個想法。

33

正確的答案是使用Ruby的Pathname(自1.8.7以來的內置類,而不是寶石)。

看到代碼:

require 'pathname' 

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

這樣做會丟棄信息的路徑是否絕對或相對的。要檢測這一點,您可以撥打absolute?方法Pathname

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

+1

我同意使用路徑名。我們也可以用tap方法寫如下:'[] .tap {| x | Pathname.new( 「/家/古比/ bigproject/now_with_bugs_fixed/32」)each_filename {|。d | x << d}}' – 2014-02-06 10:36:27

+0

您好,先生,我們一起設法得到了一個完美的解決方案。再次感謝。 – 2014-02-06 12:32:24

+0

值得注意的是,在絕對路徑的情況下,'File.join(Pathname(path).each_filename.to_a)!= path'。 – 2014-02-25 15:25:21