在Linux下的Ruby中不敏感地打开文件大小写

在Linux下的Ruby中不敏感地打开文件大小写,ruby,linux,case-insensitive,Ruby,Linux,Case Insensitive,在Linux下,有没有一种方法可以在Ruby中不敏感地打开文件案例?例如,给定字符串foo.txt,我可以打开文件foo.txt 一种可能的方法是读取目录中的所有文件名并手动搜索列表中所需的文件,但我正在寻找一种更直接的方法。您可以使用Dir.glob和FNM\u CASEFOLD标志来获取除case之外与给定名称匹配的所有文件名的列表。然后,只需在结果数组上使用first即可返回任何结果,或者使用minu\by可获得与原始数组大小写最匹配的结果 def find_file(f) Dir.g

在Linux下,有没有一种方法可以在Ruby中不敏感地打开文件案例?例如,给定字符串
foo.txt
,我可以打开文件
foo.txt


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

您可以使用Dir.glob和
FNM\u CASEFOLD
标志来获取除case之外与给定名称匹配的所有文件名的列表。然后,只需在结果数组上使用
first
即可返回任何结果,或者使用
minu\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"]

虽然您不能使
打开
不区分大小写,但您可以非常简洁地编写您建议的目录搜索。e、 g

filename = Dir.glob('foo.txt', File::FNM_CASEFOLD).first
if filename
  # use filename here
else
  # no matching file
end
请注意,虽然这看起来不正确或过时

备选方案

如果您担心使用
FNM\u 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

如果多个文件匹配怎么办?随便挑一个?@Ignacio:是的,这是唯一合理的选择。但在我的情况下,这种情况不太可能发生。对于大多数
IO
File
方法,Ruby只是将所有内容传递给libc。所以,我想这可能基本上是随机工作的,也可能不是,这取决于你的操作系统的libc是如何工作的。@Jörg谢谢。我已经用一些其他的想法更新了答案,避免了依赖于
FNM\u CASEFOLD
。在我的系统中,FNM\u CASEFOLD在Ruby 2.0.0中受到尊重,但在Ruby 2.2.0中被忽略。绝对不可靠。