2010-09-06 25 views
13

¿Hay alguna forma de abrir un archivo sin distinción entre mayúsculas y minúsculas en Ruby en Linux? Por ejemplo, dada la cadena foo.txt, ¿puedo abrir el archivo FOO.txt?Abre un archivo sin distinción de mayúsculas y minúsculas en Ruby en Linux

Una posible forma sería leer todos los nombres de los archivos en el directorio y buscar manualmente en la lista el archivo requerido, pero estoy buscando un método más directo.

+2

¿Qué pasa si coinciden varios archivos? Elija uno de ellos al azar? –

+0

@Ignacio: Sí, esa es la única opción razonable. Pero ese caso es poco probable en mi situación. – imgx64

Respuesta

17

Mientras que no se puede hacer open mayúsculas y minúsculas se puede escribir la búsqueda en el directorio que usted sugirió bastante concisa. p.ej.

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

Tenga en cuenta que mientras que el documentation suggests that FNM_CASEFOLD can't be used with glob esto parece ser incorrecto o fuera de fecha.

Alternativas

Si usted está preocupado acerca del uso de FNM_CASEFOLD luego un par de alternativas son:

filename = Dir.glob('*').find { |f| f.downcase == 'foo.txt' } 

o escribir un pequeño método para construir un caso pegote insensible para un nombre de archivo dado:

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]" 

y entonces usted puede hacer:

filename = Dir.glob(ci_glob('foo.txt')).first 
+1

Para la mayoría de los métodos 'IO' y' File', Ruby simplemente pasa todo a libc. Por lo tanto, supongo que esto básicamente podría funcionar al azar o no, dependiendo de cómo funciona la libc de su sistema operativo. –

+0

@ Jörg Gracias. He actualizado la respuesta con un par de otras ideas que evitan la necesidad de confiar en 'FNM_CASEFOLD'. – mikej

+0

En mi sistema, FNM_CASEFOLD se respeta en Ruby 2.0.0 pero se ignora en Ruby 2.2.0. Definitivamente no es confiable. – Lupius

1

Puede usar Dir.glob con el indicador FNM_CASEFOLD para obtener una lista de todos los nombres de archivo que coinciden con el nombre de pila, excepto en el caso. A continuación, puede utilizar first en la matriz resultante para obtener algún resultado o utilizar min_by para obtener el que mejor se adapte al caso de 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"] 
Cuestiones relacionadas