我如何判断某个路径上是否存在符号 link?

How can I tell if a symbolic link exists at a certain path?

我有一个原始文件 /path/to/foo.txt 和一个符号 link,/other/path/to/foo.txt。我删除了 /path/to/foo.txt,但保留了符号 link。 如何使用 Cocoa APIs 判断符号 link 仍然存在?


我使用 standard/recommended FileManager.fileExists(atPath:) 找到了这个。对于不熟悉 API 的任何人来说,这里的问题是它遍历 symlinks。所以,当我这样做时:

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

它returnsfalse,因为它看到我给它一个symlink解析了,然后看到解析的路径下没有文件。

如文档所述:

If the file at path is inaccessible to your app, perhaps because one or more parent directories are inaccessible, this method returns false. If the final element in path specifies a symbolic link, this method traverses the link and returns true or false based on the existence of the file at the link destination.

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

您不需要 need/use FileManager 来处理这个。而且你不应该再为任何东西使用字符串文件路径。

从文件 URL 开始 — "/other/path/to/foo.txt" 的 URL 版本。现在读取文件的 .isSymbolicLink 资源键并查看它是否是符号 link。如果是,但如果指向的文件不存在,你就知道你的 link 已经坏了。

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

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)
    }
}

替换 fileExists(atPath:) 的解决方案是使用 attributesOfItem(atPath:) returns 节点类型 (FileAttributeKey.type) 如果 file/node 不存在则抛出错误代码=260。

所以我的 "interpretation" 是这样的:

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 的技巧:-)

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

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

node.isDirectory      >> false
node.isRegularFile    >> false
node.isSymbolicLink   >> true