Откройте файл без учета регистра в Ruby под Linux

Есть ли способ открыть файл case-insensitively в Ruby под Linux? Например, с учетом строки foo.txt можно открыть файл foo.txt?

Один из возможных способов - это прочитать все имена файлов в каталоге и вручную найти список для требуемого файла, но я ищу более прямой метод.

Ответы

Ответ 1

В то время как вы не можете сделать open нечувствительным к регистру, вы можете написать поиск в каталоге, который вы предложили достаточно кратко. например.

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

Обратите внимание, что в то время как документация предполагает, что FNM_CASEFOLD не может использоваться с 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

Ответ 2

Вы можете использовать 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"]