2013-08-08 1 views
7

Mac обычно работает с файловой системой HFS +, которая нормализует пути. То есть, если вы сохраните файл с акцентом é в нем (например, u'\xe9'), а затем выполните os.listdir, вы увидите, что имя файла преобразовано в u'e\u0301'. Это нормальная нормализация Unicode NFD, которую может обрабатывать the Python unicodedata module. К сожалению, HFS + не полностью соответствует NFD, что означает, что некоторые пути не будут нормализованы, например, 福 (u'\ufa1b') не будет изменен, хотя его форма NFD равна u'\u798f'.Как преобразовать путь в Mac OS X путь, нормальную форму почти-NFD?

Итак, как выполнить нормализацию в Python? Я был бы в порядке, используя собственные API, если я могу назвать их с Python.

+0

Глупый взлом, который должен работать: создайте пустой файл в каталоге temp и перечислите его. – Dougal

+0

Обратите внимание, что взлом файла temp очень дорог, если вы считаете, что вам может быть передан путь, который представляет собой глубокую структуру каталогов. Вам нужно будет сделать os.makedirs и прикоснуться к файлу, а затем перейти в структуру каталогов, чтобы увидеть, что создано. –

+0

Предположительно нормализация согласована между именами каталогов и файлов, поэтому вы можете разделить части и создавать файлы только для тех, у которых есть возможно изменение символов, чтобы избежать прогулок по каталогам. Но да, это, очевидно, не очень хорошее решение. – Dougal

ответ

5

Ну, решил написать решение Python, поскольку связанный с ним другой вопрос, на который я указал, был более Objective-C.

Сначала вам необходимо установить https://pypi.python.org/pypi/pyobjc-core и https://pypi.python.org/pypi/pyobjc-framework-Cocoa. Тогда должно работать:

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 

Обратите внимание, что NSString.fileSystemRepresentation(), кажется, также принимает ввод ул. У меня были случаи, когда он возвращал мусор в этом случае, поэтому я думаю, что использовать его с юникодом было бы безопаснее. Он всегда возвращает тип str, поэтому вам нужно преобразовать обратно в unicode.

Смежные вопросы