2009-12-04 13 views
5

Gibt es eine einfache Möglichkeit, den "echten" Pfad für die Groß- und Kleinschreibung von einem Pfad für alle Kleinbuchstaben zu erhalten. Wie die Umkehrung von os.path.normcase.Umgekehrte Version von os.path.normalcase unter Windows

Betrachten wir zum Beispiel das Verzeichnis:

c:\StackOverFlow 

Wenn ich die folgenden Ausschnitt haben, wie d_real zu erhalten?

>>> import os 
>>> d = os.path.normcase('C:\\StackOverFlow') # convert to lower case 
>>> d 
'c:\\stackoverflow' 
>>> d_real = ... # should give 'C:\StackOverFlow' with the correct case 
+0

'os.path.join ('c:', 'Stackoverflow')' gibt Ihnen 'c: stackoverflow', * nicht *' c: \ stackoverflow', wie es in der Dokumentation erklärt (= Pfad relativ zum aktuellen Verzeichnis auf dem angegebenen Laufwerk). –

+0

Ja, ich habe meinen Beispielcode nicht überprüft. Wird es reparieren. Vielen Dank. – pkit

Antwort

0

Schmutzige Hack Ansatz,

import glob 
... 
if os.path.exists(d): 
    d_real = glob.glob(d + '*')[0][:len(d)] 
+0

glob.glob (d + '*') gibt eine leere Liste unter Windows zurück (zumindest für mich) – jhwist

+0

@jhwist, ich habe es unter Windows getestet und es funktioniert. Was hast du für "d" benutzt? –

+0

Hmmm, könnte eine Verwechslung von cygwin-style Pfaden sein, meine 'd =" c:/existing_file "' – jhwist

1

ich diese Lösung nicht in Betracht ziehen würden einfach, aber was können Sie ist:

import os 
d = os.path.normcase('C:\\StackOverFlow') 
files = os.listdir(os.path.dirname(d)) 
for f in files: 
    if not d.endswith(f.lower()): 
    continue 
    else 
    real_d = os.path.join(os.path.dirname(d), f) 

Es ist wahrscheinlich nicht effizient (je nach die Anzahl der Dateien im Verzeichnis). Es muss für die Pfad-Komponenten optimiert werden (meine Lösung korrigiert nur den Fall des Dateinamens und kümmert sich nicht um die Verzeichnisnamen). Vielleicht könnte auch os.walk hilfreich sein, den Baum zu durchqueren.

-1

Definitiv hässlich, aber Spaß:

def getRealDirPath(path): 
    try: 
     open(path) 
    except IOError, e: 
     return str(e).split("'")[-2] 

Natürlich:

  • funktioniert nur mit Verz
  • wird Buggy, wenn dir aus einem anderen Grund nicht geöffnet werden kann

Aber kann immer noch nützlich sein, wenn Sie es nicht für "Leben oder Tod" Art von Code benötigen.

Versucht, die Standardbibliothek zu finden, um zu finden, wie sie den echten Pfad gefunden haben, aber nicht finden konnten. Muss

in C. sein, dass die schmutzige Hack des Tages war, werden wir beim nächsten Mal einen regexp auf dem Stacktrace verwenden, nur weil wir

+0

Funktioniert nicht ... – schlamar

0

:-) können Sie diese GetShortPathName und GetLongPathName von Verkettungs tun können. Dies kann theoretisch nicht funktionieren, da Sie kurze Dateinamen unter Windows mit einigen Konfigurationseinstellungen deaktivieren können. Hier ist ein Beispielcode mit ctypes:

def normcase(path): 
    import ctypes 
    GetShortPathName = ctypes.windll.kernel32.GetShortPathNameA 
    GetLongPathName = ctypes.windll.kernel32.GetLongPathNameA 
    # First convert path to a short path 
    short_length = GetShortPathName(path, None, 0) 
    if short_length == 0: 
     return path 
    short_buf = ctypes.create_string_buffer(short_length) 
    GetShortPathName(path, short_buf, short_length) 
    # Next convert the short path back to a long path 
    long_length = GetLongPathName(short_buf, None, 0) 
    long_buf = ctypes.create_string_buffer(long_length) 
    GetLongPathName(short_buf, long_buf, long_length) 
    return long_buf.value 
+0

Das funktioniert einfach großartig, außer dass das Laufwerk oder die Netzwerkkomponente eines Pfades immer noch ein beliebiger Fall sein kann. Ich fand es nützlich, 'Teile = os.path.splitdrive (os.path.normcase (Pfad))' 'path = Teile [0] .upper() + Teile [1]' an den Anfang der Funktion, so dass ich Großbuchstaben Laufwerksbuchstaben und Kleinbuchstaben Netzwerkpfade hätte. – garlon4

+0

Hinweis: Für diese Dateisystem-abhängige Lösung überprüfen Sie zuerst, ob ** short filename generation ** auf Windows-Volumes ausgeschaltet ist ('fsutil.exe 8dot3name query C:') - das wird für die Performance empfohlen, es sei denn, 16bit-Apps werden noch bereitgestellt. – kxr

1

Verwendung von Standard-lib nur funktioniert dies ein auf allen Bahnteile/subdirs (außer Laufwerksbuchstaben):

def casedpath(path): 
    r = glob.glob(re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', path)) 
    return r and r[0] or path 

Und diese Griffe UNC-Pfade zusätzlich:

def casedpath_unc(path): 
    unc, p = os.path.splitunc(path) 
    r = glob.glob(unc + re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', p)) 
    return r and r[0] or path 
+0

@ Alecz, Dateien sind der Hauptanwendungsfall. Kann das Problem nicht reproduzieren. Beispiel? Bekannt: Es wird kein möglicher Laufwerksbuchstabe (und UNC-Dienstname) in Großbuchstaben eingegeben. konvertiert keinen Schrägstrich -> Backslash. Es macht nichts an Dateien/Verzeichnissen, die nicht wirklich existieren (Existenz eines nur partiellen Pfades). Oder vielleicht haben Sie einen Testpfad mit falschem/fehlendem Backslash-Escaping oder fehlendem Raw-String-Präfix r verwendet - z. '" einige \\ false \ rawpath.txt "'. – kxr

+0

Ich kann das auch nicht mehr reproduzieren. Es funktioniert perfekt, ich denke, das ist eine sehr saubere Lösung. Ich werde meinen anderen Kommentar löschen. Vielen Dank! – Alecz

Verwandte Themen