在Linux下在Ruby中打开一个不区分大小写的文件

时间:2010-09-06 13:46:26

标签: ruby linux case-insensitive

有没有办法在Linux下在Ruby中不区分大小写地打开文件?例如,给定字符串foo.txt,我可以打开文件FOO.txt吗?

一种可能的方法是读取目录中的所有文件名并手动搜索列表中的所需文件,但我正在寻找更直接的方法。

2 个答案:

答案 0 :(得分:18)

虽然您无法使open不区分大小写,但您可以非常简洁地编写您建议的目录搜索。 e.g。

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

或编写一个小方法来为给定的文件名构建不区分大小写的glob:

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 :(得分: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"]