Open a file case-insensitively in Ruby under Linux

人盡茶涼 提交于 2019-12-04 18:16:23

问题


Is there a way to open a file case-insensitively in Ruby under Linux? For example, given the string foo.txt, can I open the file FOO.txt?

One possible way would be reading all the filenames in the directory and manually search the list for the required file, but I'm looking for a more direct method.


回答1:


Whilst you can't make open case insensitive you can write the directory search you suggested quite concisely. e.g.

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

Note that whilst the documentation suggests that FNM_CASEFOLD can't be used with glob this appears to be incorrect or out of date.

Alternatives

If you're concerned about using FNM_CASEFOLD then a couple of alternatives are:

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

or write a little method to build a case insensitive glob for a given filename:

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

and then you can do:

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



回答2:


You can use Dir.glob with the FNM_CASEFOLD flag to get a list of all filenames that match the given name except for case. You can then just use first on the resulting array to get any result back or use min_by to get the one that matches the case of the orignial most closely.

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


来源:https://stackoverflow.com/questions/3651952/open-a-file-case-insensitively-in-ruby-under-linux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!