【问题标题】:Open a file case-insensitively in Ruby under LinuxLinux 下 Ruby 不区分大小写地打开文件
【发布时间】:2010-09-06 13:46:25
【问题描述】:

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

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

【问题讨论】:

  • 如果多个文件匹配怎么办?随便选一个?
  • @Ignacio:是的,这是唯一合理的选择。但在我的情况下,这种情况不太可能发生。

标签: ruby linux case-insensitive


【解决方案1】:

虽然您不能使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' }

或编写一个小方法来为给定的文件名构建一个不区分大小写的 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

【讨论】:

  • 对于大多数IOFile 方法,Ruby 只是将所有内容传递给libc。所以,我想这可能基本上是随机的,取决于你的操作系统的 libc 是如何工作的。
  • @Jörg 谢谢。我已经用其他一些想法更新了答案,避免了依赖FNM_CASEFOLD
  • 在我的系统上,FNM_CASEFOLD 在 Ruby 2.0.0 中受到尊重,但在 Ruby 2.2.0 中被忽略。绝对不可靠。
【解决方案2】:

您可以使用带有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"]

【讨论】:

    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2017-11-08
    • 2012-03-24
    • 1970-01-01
    • 2012-12-01
    相关资源
    最近更新 更多