在 macOS 上测试文件名是不是相等,尤其是在 HFS+ 和 APFS 上

Posted

技术标签:

【中文标题】在 macOS 上测试文件名是不是相等,尤其是在 HFS+ 和 APFS 上【英文标题】:Testing file names on macOS for equality, especially on HFS+ and APFS在 macOS 上测试文件名是否相等,尤其是在 HFS+ 和 APFS 上 【发布时间】:2018-03-09 12:20:56 【问题描述】:

Apple 的新文件系统 APFS 带来了测试文件名相等性的新规则,它们与 HFS 不同。我正在寻找正确的方法来比较两个名称是否相等,特别是对于 APFS,但为了完整性,添加一个用于 HFS+ 检查并没有什么坏处。

为什么?因为我需要能够判断我在目录中找到的文件名是否与特定模式匹配,例如包含某个子字符串。为此,我需要匹配文件系统和 Finder 用于比较名称的确切规则。

对于这些文件系统的区分大小写的变体,这很容易,因为按字节比较就足够了,我相信(假设两个字符串使用相同的编码)。

对于不区分大小写的 HFS+,我认为甚至有一个特殊的比较选项,但我在 NSStringCompareOptions 中找不到。我认为这是必要的,因为 HFS+ 使用的是旧版本的 Unicode 标准。我引用了 TN1150(很遗憾,它似乎不再在 Apple 网站上提供):

Unicode 微妙之处

HFS Plus 大量使用 Unicode 字符串来存储文件和文件夹名称。 但是,Unicode 仍在发展中,它在文件系统中的使用带来了许多挑战。本节介绍了一些挑战,以及 HFS Plus 使用的解决方案。

重要提示: 实现不得使用其本机平台实现的 Unicode 实用程序(用于分解和比较),除非这些算法等同于此处定义的 HFS Plus 算法,并且保证永远如此。这种情况很少见。 平台算法倾向于随着 Unicode 标准而发展。 HFS Plus 算法无法进化,因为这样的进化会使现有的 HFS Plus 卷失效

啊,我想到了获得所用编码的 HFS+ 版本的部分:

注意: Mac OS 文本编码转换器提供了几个常量,可让您与存储在 HFS Plus 卷上的规范分解形式相互转换。使用 CreateTextEncoding 创建文本编码时,应将 TextEncodingBase 设置为 kTextEncodingUnicodeV2_0,将 TextEncodingVariant 设置为 kUnicodeCanonicalDecompVariant,并将 TextEncodingFormat 设置为 kUnicode16BitFormat。使用这些值可确保 Unicode 与 HFS Plus 卷上的格式相同,即使 Unicode 标准不断发展。

那么,正确比较 HFS+ 和 APFS 名称的现代方法是什么?

【问题讨论】:

所以,@thomas-tempelmann,有没有想过 APFS/HFS+ 如何比较文件名来决定它们何时被视为相等/小于/大于不区分大小写? 很遗憾,没有。在 macOS 上运行时,至少可以使用 NSString 的fileSystemRepresentation 等函数对名称进行归一化,然后比较结果。理想情况下,我们需要在 NSString 中为此设置一个特殊的比较选项,但我无法确定。 【参考方案1】:

我通过读取原始数据比较了两个文件系统。在HFS plus目录文件和文件属性中,文件名Test.jpg存储为0x0054006500730074002E006A00700067

在 Apple 文件系统中,我们有 4kb 块。 Blocktype 0x0300 BlockID 0x07040000 00000000 与目录文件相当。 Blocktype 0x0300 BlockID 0x11040000 00000000 是apple finder 信息,包括文件大小、磁盘大小和指向文件所在块的小端序指针。 文件名 Test.jpg 存储为 0x546573742E6A7067。我从来没有在我的 iMac 上使用过除 Ascii 0-127 以外的字符的文件名,经过尝试后发现可以在 APFS 和 HFS plus 上的文件名中使用扩展的 ascii、unicode 和笑脸。

APFS 没有文档记录,我们所知道的一切都是从逆向工程中学到的。

有关 APFS 的其他信息,请参阅 Cugu's blog

【讨论】:

好吧,我是@cugu_pio 的 apfs.ksy 文件的合著者,所以我在这方面遥遥领先 :) 很高兴在这里见到你!

以上是关于在 macOS 上测试文件名是不是相等,尤其是在 HFS+ 和 APFS 上的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ios XCTestCase 中对两个对象不相等进行单元测试

小科普 | 在Win10上拥有MacOS空格速览体验!

如何以编程方式确定文件是不是位于 Linux 和/或 macOS 的网络文件系统(NFS 或 SMB)上?

我可以安全地 gitignore “._” 前缀文件吗

在 iOS 上使用 Airplay 时显示推送通知?

测试列表是不是包含 Clojure 中的特定值