2011-12-11 13 views
8

Ho bisogno di caricare un file dato il suo nome, ma il nome che ottengo è case insensitive. "A.txt" potrebbe effettivamente essere "a.txt". Come fare questo nel modo più veloce (non generare tutti i nomi possibili e provarli ciascuno)?Nome file non sensibile al maiuscolo?

+0

quale sistema operativo stai? – vdbuilder

+0

Non importa, il nome che ottengo (che è senza distinzione tra maiuscole e minuscole) viene analizzato da un file di script. –

+0

Il sistema operativo (e in effetti il ​​filesystem) sono certamente rilevanti qui. – Johnsyweb

risposta

6

È possibile elencare la directory in cui si trova il file (os.listdir) e verificare se esistono corrispondenze per il nome file. La corrispondenza può essere effettuata con un numero inferiore di nomi di file e confronti.

+0

Sì, ma è efficiente? Considerando che la cartella può contenere migliaia di file? –

+4

@ user975135: Non mi preoccuperei dell'inefficienza finché non avremo provato questo approccio ed è troppo lento per le vostre esigenze. – dreamlax

+0

Beh, ho elaborato migliaia di stringhe contemporaneamente con Python, quindi penso che non dovrei ignorarlo se c'è un altro modo. –

1

Creare un elenco di directory; e creare un dizionario contenente una mappatura di nomi di file maiuscoli ai loro nomi di file reali. Quindi, inserisci l'input in maiuscolo e cercalo nel dizionario.

5

Non è possibile farlo senza tenere un elenco di directory e prendere entrambi gli elementi che si stanno cercando e ciascuno nella directory in un caso comune per il confronto. Il filesystem è case sensitive e questo è tutto quello che c'è da fare.

Ecco una funzione (beh, due) che ho scritto per eseguire completamente, facendo corrispondere un nome file in modo insensibile, in modo ricorsivo: http://portableapps.hg.sourceforge.net/hgweb/portableapps/development-toolkit/file/775197d56e86/utils.py#l78.

def path_insensitive(path): 
    """ 
    Get a case-insensitive path for use on a case sensitive system. 

    >>> path_insensitive('/Home') 
    '/home' 
    >>> path_insensitive('/Home/chris') 
    '/home/chris' 
    >>> path_insensitive('/HoME/CHris/') 
    '/home/chris/' 
    >>> path_insensitive('/home/CHRIS') 
    '/home/chris' 
    >>> path_insensitive('/Home/CHRIS/.gtk-bookmarks') 
    '/home/chris/.gtk-bookmarks' 
    >>> path_insensitive('/home/chris/.GTK-bookmarks') 
    '/home/chris/.gtk-bookmarks' 
    >>> path_insensitive('/HOME/Chris/.GTK-bookmarks') 
    '/home/chris/.gtk-bookmarks' 
    >>> path_insensitive("/HOME/Chris/I HOPE this doesn't exist") 
    "/HOME/Chris/I HOPE this doesn't exist" 
    """ 

    return _path_insensitive(path) or path 


def _path_insensitive(path): 
    """ 
    Recursive part of path_insensitive to do the work. 
    """ 

    if path == '' or os.path.exists(path): 
     return path 

    base = os.path.basename(path) # may be a directory or a file 
    dirname = os.path.dirname(path) 

    suffix = '' 
    if not base: # dir ends with a slash? 
     if len(dirname) < len(path): 
      suffix = path[:len(path) - len(dirname)] 

     base = os.path.basename(dirname) 
     dirname = os.path.dirname(dirname) 

    if not os.path.exists(dirname): 
     dirname = _path_insensitive(dirname) 
     if not dirname: 
      return 

    # at this point, the directory exists but not the file 

    try: # we are expecting dirname to be a directory, but it could be a file 
     files = os.listdir(dirname) 
    except OSError: 
     return 

    baselow = base.lower() 
    try: 
     basefinal = next(fl for fl in files if fl.lower() == baselow) 
    except StopIteration: 
     return 

    if basefinal: 
     return os.path.join(dirname, basefinal) + suffix 
    else: 
     return 
1

Questa è una semplice funzione ricorsiva per la ricerca di Eli suggerisce di cui sopra:

def find_sensitive_path(dir, insensitive_path): 

    insensitive_path = insensitive_path.strip(os.path.sep) 

    parts = insensitive_path.split(os.path.sep) 
    next_name = parts[0] 
    for name in os.listdir(dir): 
     if next_name.lower() == name.lower(): 
      improved_path = os.path.join(dir, name) 
      if len(parts) == 1: 
       return improved_path 
      else: 
       return find_sensitive_path(improved_path, os.path.sep.join(parts[1:])) 
    return None 
Problemi correlati