Details
-
Bug
-
Resolution: Done
-
P3: Somewhat important
-
5.12.3
-
None
-
-
d01693733f6c1ebe6b3709f9c1284239ce3b5354 (qt/qtbase/5.12)
Description
Enviroments:
- macOS, 10.14.5
- Python, 3.7.3
- PySide2, 5.12.3
A minimal example:
from PySide2.QtCore import QDir import os import fnmatch import unicodedata if __name__ == "__main__": task = ["r\u00E9-0.txt", "re\u0301-1.txt"] for one in task: print("open", one, ascii(one), ascii(unicodedata.normalize("NFC", one))) with open(one, "w") as f: f.write(one) for e in os.listdir("."): if fnmatch.fnmatch(e, "*.txt"): print("os.listdir", e, ascii(e)) for e in QDir(".").entryInfoList(["*.txt"]): print("QDir", e.fileName())
Terminal output on one APFS disk:
open ré-0.txt 'r\xe9-0.txt' 'r\xe9-0.txt' open ré-1.txt 're\u0301-1.txt' 'r\xe9-1.txt' os.listdir ré-0.txt 'r\xe9-0.txt' os.listdir ré-1.txt 're\u0301-1.txt' QDir ré-1.txt
Terminal output on one HFS+ disk:
open ré-0.txt 'r\xe9-0.txt' 'r\xe9-0.txt' open ré-1.txt 're\u0301-1.txt' 'r\xe9-1.txt' os.listdir ré-0.txt 're\u0301-0.txt' os.listdir ré-1.txt 're\u0301-1.txt' QDir ré-0.txt QDir ré-1.txt
Related source, qfilesystemiterator_unix.cpp:
bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) { if (!dir) return false; for (;;) { dirEntry = QT_READDIR(dir); if (dirEntry) { // process entries with correct UTF-8 names only if (QFile::encodeName(QFile::decodeName(dirEntry->d_name)) == dirEntry->d_name) { fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath()); metaData.fillFromDirEnt(*dirEntry); return true; } } else { break; } } lastError = errno; return false; }
Related source, qfile.h:
#if defined(Q_OS_DARWIN) // Mac always expects filenames in UTF-8... and decomposed... static inline QByteArray encodeName(const QString &fileName) { return fileName.normalized(QString::NormalizationForm_D).toUtf8(); } static QString decodeName(const QByteArray &localFileName) { // note: duplicated in qglobal.cpp (qEnvironmentVariable) return QString::fromUtf8(localFileName).normalized(QString::NormalizationForm_C); } #else static inline QByteArray encodeName(const QString &fileName) { return fileName.toLocal8Bit(); } static QString decodeName(const QByteArray &localFileName) { return QString::fromLocal8Bit(localFileName); } #endif
Reference of APFS on filename handling:
How does Apple File System handle filenames?