4

我有一个原始文件 ./path/to/foo.txt和指向它的符号链接/other/path/to/foo.txt. 我删除/path/to/foo.txt,但将符号链接保留在原地。如何使用 Cocoa API 判断符号链接仍然存在?


我通过使用标准/推荐找到了这一点FileManager.fileExists(atPath:)。对于不熟悉该 API 的任何人来说,这里的问题是它遍历符号链接。所以,当我这样做时:

FileManager.default.fileExists(atPath: "/other/path/to/foo.txt")

它返回false,因为它看到我给了它一个符号链接并解析了它,然后看到解析的路径中没有文件。

正如文档所说:

如果path您的应用程序无法访问 at 的文件,可能是因为一个或多个父目录无法访问,则此方法返回false. 如果 in 中的最后一个元素path指定了符号链接,则此方法遍历链接并返回truefalse基于链接目标处文件的存在。

中似乎没有替代方案FileManager。所以,我想知道我是否可以调用 Cocoa API 来判断那里是否存在符号链接,或者我是否必须求助于 C 或 Bash API。

4

3 回答 3

9

为此,您不需要/使用 FileManager。而且您不应该再使用字符串文件路径

从文件 URL 开始——您的"/other/path/to/foo.txt". 现在读取文件的.isSymbolicLink资源键并查看它是否是符号链接。如果是,但如果指向的文件不存在,则您知道您的链接已损坏。

我在操场上写了一个小测试:

let url = URL(fileURLWithPath: "/Users/mattneubelcap/Desktop/test.txt")
if let ok = try? url.checkResourceIsReachable(), ok {
    let vals = url.resourceValues(forKeys: [.isSymbolicLinkKey])
    if let islink = vals.isSymbolicLink, islink {
        print("it's a symbolic link")
        let dest = url.resolvingSymlinksInPath()
        let report = dest != url ? "It exists" : "It doesn't exist"
        print(report)
    }
}
于 2018-08-17T19:06:26.523 回答
3

这是一个更简单的方法:Fondation/FileManger/FileWrapper

let node = try FileWrapper(url: URL(fileURLWithPath: "/PATH/file.link"), options: .immediate)

node.isDirectory      >> false
node.isRegularFile    >> false
node.isSymbolicLink   >> true
于 2019-10-12T09:29:06.610 回答
2

替换 fileExists(atPath:) 的解决方案是使用 attributesOfItem(atPath:),它返回节点的类型 (FileAttributeKey.type),如果文件/节点不存在,则抛出错误 Code=260。

所以这里是我的“解释”:

func nodeExists(atPath path: String) -> FileType? {
do {
    let attribs = try fm.attributesOfItem(atPath: path)
    if let type = attribs[FileAttributeKey.type] {
        switch (type as! FileAttributeType) {
            case FileAttributeType.typeDirectory: return .directory
            case FileAttributeType.typeRegular: return .file
            case FileAttributeType.typeSymbolicLink: return .symlink
            default:
                return nil
            }
        }
    } catch {
        if (error as NSError).code == 260 {
            return false
        } else {
            return nil
        }
    }
}

挖掘错误代码的方法 <<< 感谢 Ben Leggiero 的技巧 :-)

于 2019-09-26T20:42:49.743 回答