Откройте файл без учета регистра в Ruby под Linux - PullRequest
13 голосов
/ 06 сентября 2010

Есть ли способ открыть файл без учета регистра в Ruby под Linux?Например, учитывая строку foo.txt, могу ли я открыть файл FOO.txt?

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

Ответы [ 2 ]

18 голосов
/ 06 сентября 2010

Хотя вы не можете сделать 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' }

или напишите небольшой метод для создания нечувствительного к регистру глобуса для заданногоимя файла:

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 голос
/ 06 сентября 2010

Вы можете использовать Dir.glob с флагом FNM_CASEFOLD, чтобы получить список всех имен файлов, которые соответствуют данному имени, за исключением регистра.Затем вы можете просто использовать 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"]
...