我正在开发一个库,希望保持平台、文件系统和Python2.x/3.x独立。但是,我不知道如何以独立于平台/文件系统的方式将文件名与正则表达式匹配。
例如(在Mac上,使用IPython,Python2.7):
In[7]: from glob import glob
In[8]: !touch 'ü-0.é' # Create the file in the current folder
In[9]: glob(u'ü-*.é')
Out[9]: []
In[10]: import unicodedata as U
In[11]: glob(U.normalize('NFD', u'ü-*.é'))
Out[11]: [u'u\u0308-0.e\u0301']但是,这在Linux或Windows上是行不通的,因为我需要unicode.normalize('NFC', u'ü-*.é')。当我试图将文件名与正则表达式匹配时,也会出现同样的问题:只有在Mac上规范化为NFD的unicode正则表达式与文件名匹配,而只有NFC正则表达式匹配在Linux/Windows上读取的文件名(在这两种情况下我都使用re.UNICODE标志)。
有什么标准的方法来处理这个问题吗?
我希望,就像sys.getfilesystemencoding()返回文件系统的编码一样,也会有一个函数返回底层文件系统使用的Unicode规范化。
然而,我既找不到这样的函数,也找不到一种安全/标准的方法来对它进行特性测试。
Mac + HFS+使用NFD规范化:https://apple.stackexchange.com/a/10484
Linux + Windows使用NFC规范化:http://qerub.se/filenames-and-unicode-normalization-forms
链接到代码:https://github.com/musically-ut/seqfile/blob/feat-unicode/seqfile/seqfile.py
发布于 2015-04-30 15:48:46
我假设您希望匹配unicode 等价物文件名,例如,您期望u'\xE9*'的输入模式在任何操作系统上都匹配文件名u'\xE9qui'和u'e\u0301qui',即字符级模式匹配。
您必须理解,在Linux上,这不是默认的,在Linux中,字节被视为字节,并且不是每个文件名都是当前系统编码中的有效unicode字符串(尽管Python3使用了“代理转义”错误处理程序来将这些字符串表示为str )。
考虑到这一点,这是我的解决方案:
def myglob(pattern, directory=u'.'):
pattern = unicodedata.normalize('NFC', pattern)
results = []
enc = sys.getfilesystemencoding()
for name in os.listdir(directory):
if isinstance(name, bytes):
try:
name = name.decode(enc)
except UnicodeDecodeError:
# Filenames that are not proper unicode won't match any pattern
continue
if fnmatch.filter([unicodedata.normalize('NFC', name)], pattern):
results.append(name)
return results发布于 2015-04-27 18:29:01
我就是这样解决问题的:
import unicodedata as U
# ...
globPattern = os.path.join(folder, prefix + u'*' + suffix)
rawRegEx = prefix + u'([0-9]+)' + suffix + u'$'
# Mac uses NFD normalization for Unicode filenames while windows
# linux/windows use NFC normalization
if sys.platform.startswith('darwin'):
normalizedGlobPattern = U.normalize('NFD', globPattern)
normalizedRegEx = U.normalize('NFD', rawRegEx)
else:
normalizedGlobPattern = U.normalize('NFC', globPattern)
normalizedRegEx = U.normalize('NFC', rawRegEx)
allFiles = glob.glob(normalizedGlobPattern)
# ...
numFilesRegEx = re.compile(normalizedRegEx, _re.UNICODE)
numberedFiles = (re.search(numFilesRegEx, f) for f in allFiles
if re.search(numFilesRegEx, f))这似乎通过了我可以在AppVeyor (Windows)、Travis (Linux)和我的笔记本电脑(Mac + HFS+)上进行的所有测试。
但是,我不确定是安全的还是,是否有更好的方法编写。例如,我不知道它是否能在装有NFS的Mac上工作。
https://stackoverflow.com/questions/29903338
复制相似问题