在符号链接后查找目录是否包含URL

时间:2017-05-12 19:13:57

标签: swift macos url filesystems

我有两个目录如下:

  • 目录 A 包含文件 X
  • 目录 B 包含名为 C A 目录的别名。

因此,文件 X 有两种可能的绝对网址:/A/X/B/C/X。 ( A B 可以在我的文件系统中的任何位置。)

我需要做的是,根据目录 B file:///B/)的文件网址和文件 X 的文件网址,确定是否文件 X 位于目录 B

这是我想出的:

extension URL {

    func isIdenticalFile(to other: URL) -> Bool {
        return resolvingSymlinksInPath() == other.resolvingSymlinksInPath()
    }

    func contains(_ other: URL) -> Bool {
        guard isFileURL, other.isFileURL, let enumerator = FileManager.default.enumerator(atPath: path) else {
            return false
        }

        for subURL in enumerator.map({ appendingPathComponent($0 as! String) }) {
            if subURL.isIdenticalFile(to: other) || subURL.contains(other) {
                return true
            }
        }

        return false
    }

}

let b = URL(string: "file:///B/")!
let ax = URL(string: "file:///A/X")!
let bcx = URL(string: "file:///B/C/X")!

// Both b.contains(ax) and b.contains(bcx) are true

有更简单/更有效的方法吗?

1 个答案:

答案 0 :(得分:-1)

确定两个网址是否引用相同的更好方法 文件是比较他们的fileResourceIdentifier。来自文档:

  

一个标识符,可用于使用isEqual比较两个文件系统对象是否相等。

     

如果两个对象标识符具有相同的文件系统路径,或者路径链接到同一文件系统上的同一inode,则它们是相同的。系统重新启动时,此标识符不会持久存在。

确定资源标识符应该比完全更快 解析文件路径。此外,它还检测到硬链接 同一个文件。

更多备注:

  • 您的代码中的递归不是必需的,因为枚举器 已经做了“深度”枚举。
  • 使用enumerator(at: self, ...),您可以获得网址的枚举器 而不是路径,因此您不必构建subURL

然后代码可能如下所示:

extension URL {

    // Helper property get the resource identifier:
    private var identifier: NSObjectProtocol? {
        return (try? resourceValues(forKeys: [.fileResourceIdentifierKey]))?.fileResourceIdentifier
    }

    func contains(_ other: URL) -> Bool {
        guard isFileURL, other.isFileURL else {
            return false
        }
        guard let otherId = other.identifier else {
            return false
        }

        guard let enumerator = FileManager.default.enumerator(at: self, includingPropertiesForKeys: [.fileResourceIdentifierKey]) else {
            return false
        }

        for case let subURL as URL in enumerator {
            if let fileId = subURL.identifier, fileId.isEqual(otherId) {
                return true
            }
        }

        return false
    }

}