2010-09-06 52 views
13

有沒有辦法在Linux下在Ruby中不區分大小寫打開文件?例如,給定字符串foo.txt,我可以打開文件FOO.txt嗎?在Linux下以Ruby打開一個不區分大小寫的文件

一種可能的方式是讀取目錄中的所有文件名並手動搜索所需文件的列表,但我正在尋找更直接的方法。

+2

如果多個文件匹配會怎麼樣?隨機挑選其中一個? – 2010-09-06 13:50:37

+0

@Ignacio:是的,那是唯一合理的選擇。但這種情況在我的情況下不太可能發生。 – imgx64 2010-09-06 14:14:44

回答

17

雖然你不能讓open不區分大小寫,但你可以寫出你建議的目錄搜索很簡潔。例如

filename = Dir.glob('foo.txt', File::FNM_CASEFOLD).first 
if filename 
    # use filename here 
else 
    # no matching file 
end 

請注意,雖然documentation suggests that FNM_CASEFOLD can't be used with glob這看起來不正確或過時。

替代

如果你擔心使用FNM_CASEFOLD那麼幾個選擇是:

filename = Dir.glob('*').find { |f| f.downcase == 'foo.txt' } 

或者寫一個小方法來建立一個不區分大小寫的水珠對於一個給定的文件名:

def ci_glob(filename) 
    glob = '' 
    filename.each_char do |c| 
    glob += c.downcase != c.upcase ? "[#{c.downcase}#{c.upcase}]" : c 
    end 
    glob 
end 

irb(main):024:0> ci_glob('foo.txt') 
=> "[fF][oO][oO].[tT][xX][tT]" 

然後你可以這樣做:

filename = Dir.glob(ci_glob('foo.txt')).first 
+1

對於大多數'IO'和'File'方法,Ruby只是將所有內容傳遞給libc。所以,我想這可能基本上隨機工作或不工作,這取決於您的操作系統的libc如何工作。 – 2010-09-06 14:53:57

+0

@Jörg謝謝。我已經用一些其他想法更新了答案,避免了需要依賴「FNM_CASEFOLD」。 – mikej 2010-09-06 15:44:09

+0

在我的系統上,FNM_CASEFOLD在Ruby 2.0.0中很受尊敬,但在Ruby 2.2.0中被忽略。絕對不可靠。 – Lupius 2015-12-02 21:05:11

1

您可以使用Dir.glob和FNM_CASEFOLD標誌來獲取與除了大小寫外的給定名稱匹配的所有文件名的列表。然後,您可以在結果數組上使用first以獲取任何結果,或使用min_by來獲得與最接近orignial的情況相匹配的結果。

def find_file(f) 
    Dir.glob(f, File::FNM_CASEFOLD).min_by do |f2| 
    f.chars.zip(f2.chars).count {|c1,c2| c1 != c2} 
    end 
end 

system "touch foo.bar" 
system "touch Foo.Bar" 
Dir.glob("FOO.BAR", File::FNM_CASEFOLD) #=> ["foo.bar", "Foo.Bar"] 
find_file("FOO.BAR") #=> ["Foo.Bar"] 
相關問題