, , Alex L answer, :
import os, unicodedata
def gettruecasepath(path):
if not os.path.lexists(path):
raise OSError(2, u'No such file or directory', path)
isosx = sys.platform == u'darwin'
if isosx:
path = unicodedata.normalize('NFD', path)
parentpath, leaf = os.path.split(path)
if leaf not in [ u'.', u'..' ]:
leaf_lower = leaf.lower()
found = False
for leaf in os.listdir(u'.' if parentpath == u'' else parentpath):
if leaf_lower == leaf.lower():
found = True
if isosx:
leaf = unicodedata.normalize('NFC', leaf)
break
if not found:
raise OSError(2, u'Unexpectedly not found in ' + parentpath, leaf_lower)
if parentpath not in [ u'', u'.', u'..', u'/', u'\\' ] and \
not (sys.platform == u'win32' and
os.path.splitdrive(parentpath)[1] in [ u'\\', u'/' ]):
parentpath = gettruecasepath(parentpath)
return os.path.join(parentpath, leaf)
def istruecasepath(path):
return gettruecasepath(path) == unicodedata.normalize('NFC', path)
gettruecasepath() , ( ), :
- Unicode:
- Python 3.x: Unicode - .
- Python 2.x: :
u; , u'Motörhead'; str : , , strVar.decode('utf8')
- - Unicode NFC ( ). NFC OSX, (HFS +) NFD ( ).
NFC , , NFD, Python
NFC NFD () . . . - ( ,
. ..), , , Windows \ . - Windows share/UNC-share, , -.
OSError, , .- , , , Linux ext4, , .
istruecasepath() gettruecasepath() , .
. ( ), - , , . .
Native API ()
, OSX, Windows API-, .
Windows API , OSX , , - - , .
Unicode: NFC NFD
HFS + ( OSX) Unicode (NFD), Unicode , (NFC).
, -ASCII ü, , Unicode, U+00FC; NFC: "C" , u ¨ ( ) .
, ü HFS +, NFD, 2 Unicode: u (U+0075), (̈, U+0308) ; "D" , .
, Unicode 2 () , , Python, .
Python unicodedata.normalize() .
( : Unicode Unicode, Unicode , . ü ( NFC) 2 UTF-8 (U+00FC → 0xC3 0xBC), ü (NFD) 3 (U+0075 → 0x75 U+0308 → 0xCC 0x88)).