2010-09-06 2 views
13

के तहत रुबी में एक फ़ाइल केस-असंवेदनशील रूप से खोलें क्या कोई फ़ाइल केस खोलने का कोई तरीका है- रूबी में लिनक्स के तहत असंवेदनशील रूप से? उदाहरण के लिए, स्ट्रिंग foo.txt दिया गया है, क्या मैं फ़ाइल FOO.txt खोल सकता हूं?लिनक्स

एक संभावित तरीका निर्देशिका में सभी फ़ाइल नाम पढ़ेगा और मैन्युअल रूप से आवश्यक फ़ाइल के लिए सूची खोज करेगा, लेकिन मैं एक और सीधी विधि की तलाश में हूं।

+2

यदि एकाधिक फाइलें मिलती हैं तो क्या होगा? यादृच्छिक रूप से उनमें से एक उठाओ? –

+0

@Ignacio: हाँ, यह एकमात्र उचित विकल्प है। लेकिन यह मामला मेरी स्थिति में असंभव है। – imgx64

उत्तर

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

'आईओ' और 'फाइल' विधियों में से अधिकांश के लिए, रूबी बस सब कुछ libc के माध्यम से गुजरती है। इसलिए, मुझे लगता है कि यह आपके ऑपरेटिंग सिस्टम के libc कैसे काम करता है इस पर निर्भर करता है कि यह मूल रूप से यादृच्छिक रूप से काम कर सकता है या नहीं। –

+0

@ जोर्ग धन्यवाद। मैंने कुछ अन्य विचारों के साथ उत्तर अपडेट किया है जो 'FNM_CASEFOLD' पर भरोसा करने की आवश्यकता से बचें। – mikej

+0

मेरे सिस्टम पर, FNM_CASEFOLD को रूबी 2.0.0 में सम्मानित किया गया है लेकिन रूबी 2.2.0 में अनदेखा किया गया है। निश्चित रूप से विश्वसनीय नहीं है। – Lupius

1

आप FNM_CASEFOLD ध्वज के साथ Dir.glob का उपयोग कर सकते हैं ताकि मामले के अलावा दिए गए नाम से मेल खाने वाले सभी फ़ाइल नामों की एक सूची प्राप्त हो सके। आप परिणामस्वरूप सरणी पर first का उपयोग किसी भी परिणाम को वापस पाने के लिए कर सकते हैं या min_by का उपयोग कर सकते हैं ताकि वह सबसे अधिक निकटता के मामले से मेल खाता हो।

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