2013-08-08 11 views
7

Mac arbeitet normalerweise auf dem HFS + Dateisystem, welche Pfade normalisiert. Das heißt, wenn Sie eine Datei mit Akzent darin speichern (u'\xe9') zum Beispiel, und dann eine os.listdir machen, werden Sie sehen, dass der Dateiname in u'e\u0301' konvertiert wurde. Dies ist eine normale Unicode-NFD-Normalisierung, die the Python unicodedata module verarbeiten kann. Leider ist HFS + nicht vollständig konsistent mit NFD, was bedeutet, dass einige Pfade nicht normalisiert werden, zum Beispiel 福 (u'\ufa1b') wird nicht geändert, obwohl seine NFD-Form ist u'\u798f'.Wie wandere ich Pfad zu Mac OS X um, die fast-NFD-Normalform?

Also, wie die Normalisierung in Python zu tun? Ich würde gut mit nativen APIs arbeiten, solange ich sie von Python aufrufen kann.

+0

Ein dummer Hack, der funktionieren sollte: eine leere Datei in einem temporären Verzeichnis erstellen und auflisten. – Dougal

+0

Beachten Sie, dass die temporäre Datei Hack wird sehr teuer, wenn man bedenkt, dass Sie einen Pfad übergeben werden können, die eine tiefe Verzeichnisstruktur darstellt. Sie müssten os.makedirs ausführen und die Datei berühren und dann die Verzeichnisstruktur durchlaufen, um zu sehen, was erstellt wurde. –

+0

Vermutlich ist die Normalisierung zwischen Verzeichnis- und Dateinamen konsistent, so dass Sie die Teile aufgespalten konnte und nur Dateien für diejenigen machen, die haben Zeichen Fuß Verzeichnisse zu vermeiden möglicherweise verändernden. Aber ja, das ist offensichtlich keine sehr gute Lösung. – Dougal

Antwort

5

Nun, entschieden, die Python-Lösung zu schreiben, da die verwandte andere Frage, auf die ich hingewiesen habe, mehr Objective-C war.

Zuerst müssen Sie https://pypi.python.org/pypi/pyobjc-core und https://pypi.python.org/pypi/pyobjc-framework-Cocoa installieren. Dann folgt funktionieren sollte:

import sys 

from Foundation import NSString, NSAutoreleasePool 

def fs_normalize(path): 
    _pool = NSAutoreleasePool.alloc().init() 
    normalized_path = NSString.fileSystemRepresentation(path) 
    upath = unicode(normalized_path, sys.getfilesystemencoding() or 'utf8') 
    return upath 

if __name__ == '__main__': 
    e = u'\xe9' 
    j = u'\ufa1b' 
    e_expected = u'e\u0301' 

    assert fs_normalize(e) == e_expected 
    assert fs_normalize(j) == j 

Beachten Sie, dass NSString.fileSystemRepresentation() scheint auch str Eingabe zu akzeptieren. Ich hatte einige Fälle, wo es in diesem Fall Müll zurückgab, also denke ich, es wäre nur sicherer, es mit Unicode zu verwenden. Es gibt immer str typ zurück, also müssen Sie zurück in Unicode konvertieren.