I have an original file, /path/to/foo.txt
, and a symbolic link to it, /other/path/to/foo.txt
. I delete /path/to/foo.txt
, but leave the symbolic link in-place. How can I tell that the symbolic link still exists using Cocoa APIs?
I found this by using the standard/recommended FileManager.fileExists(atPath:)
. The problem here, for anyone unfamiliar with that API, is that it traverses symlinks. So, when I do this:
FileManager.default.fileExists(atPath: "/other/path/to/foo.txt")
it returns false
, because it saw that I gave it a symlink and resolved it, and then saw that there is no file at the resolved path.
As the documentation says:
If the file at
path
is inaccessible to your app, perhaps because one or more parent directories are inaccessible, this method returnsfalse
. If the final element inpath
specifies a symbolic link, this method traverses the link and returnstrue
orfalse
based on the existence of the file at the link destination.
There doesn't seem to be an alternative in FileManager
. So, I'm wondering if I can call a Cocoa API to tell if a symlink exists there, or if I'll have to resort to C or Bash APIs.
You don't need/use FileManager for this. And you should not be using string file paths for anything any more.
Start with a file URL — the URL version of your "/other/path/to/foo.txt"
. Now read the file's .isSymbolicLink
resource key and see whether it's a symbolic link. If it is, but if the file pointed to doesn't exist, you know your link has gone bad.
I wrote a little test in a playground:
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)
}
}
Here's a simpler way: Fondation/FileManger/FileWrapper
let node = try FileWrapper(url: URL(fileURLWithPath: "/PATH/file.link"), options: .immediate)
node.isDirectory >> false
node.isRegularFile >> false
node.isSymbolicLink >> true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With