Обратная версия os.path.normcase в Windows - PullRequest
6 голосов
/ 04 декабря 2009

Есть ли простой способ получить "реальный" регистр, чувствительный к регистру, из всего пути в нижнем регистре. Как и в обратном случае os.path.normcase.

Например, рассмотрим каталог:

c:\StackOverFlow

Если у меня есть следующий фрагмент, как получить 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

Ответы [ 5 ]

1 голос
/ 05 февраля 2016

При использовании только стандартной библиотеки lib она работает со всеми частями / подкаталогами пути (кроме буквы диска):

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

И этот дополнительно обрабатывает UNC-пути:

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
1 голос
/ 12 марта 2013

Вы можете сделать это, связав GetShortPathName и GetLongPathName. Теоретически это может не работать, потому что вы можете отключить короткие имена файлов в Windows с некоторыми настройками конфигурации. Вот пример кода с использованием 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
1 голос
/ 04 декабря 2009

Я бы не стал рассматривать это решение , просто , но вы можете:

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)

Это, вероятно, не эффективно (в зависимости от количества файлов в каталоге). Требуется настроить параметры пути (мое решение действительно только исправляет регистр имени файла и не заботится об именах каталогов). Кроме того, возможно os.walk может быть полезно пройти по дереву.

0 голосов
/ 05 декабря 2009

Определенно некрасиво, но весело:

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

Конечно:

  • работает только с директами
  • будет глючить, если dir не может быть открыт по другой причине

Но все еще может быть полезным, если он вам не нужен для кода типа «жизнь или смерть».

Пытался найти стандартную библиотеку, чтобы найти, как они нашли реальный путь, но не смогли его найти. Должно быть в C.

Это был грязный хак дня, в следующий раз мы будем использовать регулярное выражение на трассировке стека только потому, что можем: -)

0 голосов
/ 04 декабря 2009

Грязный взлом,

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