2009-12-04 19 views
5

Czy istnieje prosty sposób uzyskania ścieżki "rzeczywistej" z uwzględnieniem wielkości liter ze ścieżki ze wszystkimi małymi literami. Tak jak na odwrocie pliku os.path.normcase.Odwrócenie pliku os.path.normcase w systemie Windows

Rozważmy na przykład katalog:

c:\StackOverFlow 

Jeśli mam następujący fragment kodu, w jaki sposób uzyskać d_real?

>>> 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')' 'daje c: stackoverflow', * nie *' c: \ stackoverflow', jak wyjaśniono w docs (= ścieżka względna do bieżącego katalogu na określonym dysku). –

+0

Tak, nie sprawdziłem mojego przykładowego kodu. Naprawię to. Dzięki. – pkit

Odpowiedz

0

Brudny podejście hack,

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

glob.glob (d + '*') zwraca pustą listę w systemie Windows (przynajmniej dla mnie) – jhwist

+0

@jhwist, testowałem ją w systemie Windows i działa. Czego używałeś do 'd'? –

+0

Hmmm, może być mieszanką ścieżek w stylu cygwin, mój 'd =" c:/istniejący_plik "' – jhwist

1

nie uważam tego rozwiązania prosty, ale co można na to:

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) 

To chyba nie skuteczny (w zależności od liczba plików w katalogu). Wymaga on podkręcania komponentów ścieżki (moje rozwiązanie naprawia tylko przypadek nazwy pliku i nie dba o nazwy katalogów). Być może może być pomocne przechodzenie w dół drzewa przez os.walk.

-1

Zdecydowanie brzydki, ale zabawa:

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

przedmiotu:

  • działa tylko z katalogów
  • będzie buggy czy reż nie mogą być otwarte z innego powodu

Ale nadal może być przydatny, jeśli nie potrzebujesz go do kodu "życia lub śmierci".

Próbowano pobrać standardową bibliotekę lib, aby znaleźć sposób odnalezienia prawdziwej ścieżki, ale nie można jej znaleźć. Musi być w C.

to był brudny Hack dnia, następnym razem użyjemy wyrażenia regularnego na stacktrace tylko dlatego, że można :-)

+0

Nie działa ... – schlamar

0

Można to zrobić przez łańcuchowym GetShortPathName i GetLongPathName. Może to teoretycznie nie działać, ponieważ można wyłączyć krótkie nazwy plików w systemie Windows z niektórymi ustawieniami konfiguracyjnymi. Oto niektóre przykładowy kod przy użyciu 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

Działa to znakomicie, Z WYJĄTKIEM, że dysk lub składnik sieciowy ścieżki może nadal być przypadkowym przypadkiem. Zauważyłem, że warto dodać 'parts = os.path.splitdrive (os.path.normcase))' path = parts [0] .upper() + parts [1] ' na początek funkcja tak, żebym miał wielkie litery dysków i małe ścieżki sieciowe. – garlon4

+0

Uwaga: W przypadku tego rozwiązania zależnego od systemu plików najpierw sprawdź, czy ** generowanie krótkich nazw plików ** jest wyłączone na woluminach systemu Windows ('fsutil.exe, 8dot3name zapytanie C:') - które w międzyczasie jest zalecane do wydajności, chyba że 16-bitowe aplikacje wciąż są ucztami. – kxr

1

używając tylko standardowe lib, ten działa na wszystkich ścieżek części/podkatalogów (z wyjątkiem litery dysku):

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

A ten obsługuje ścieżki UNC dodatkowo:

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

@Alko pliki są głównym przypadkiem użycia. Nie można odtworzyć problemu. Przykład? Znane: Nie zawiera wielkich liter jako możliwych liter (i nazwy usługi UNC); nie konwertuje slash -> ukośnik odwrotny. nie robi nic na plikach/katalogach, które tak naprawdę już nie istnieją (istnienie tylko częściowej ścieżki). A może użyłeś ścieżki testowej z fałszywym/brakującym ukośnikiem odwrotnym lub brakiem surowego prefiksu r - np. '" some \\ false \ rawpath.txt "'. – kxr

+0

Nie mogę już tego odtworzyć. Działa idealnie, myślę, że to bardzo miłe rozwiązanie. Skasuję mój drugi komentarz. Dzięki! – Alecz

Powiązane problemy