问题
In Python 2, I can use the following code to resolve either a MacOS alias or a symbolic link:
from Carbon import File
File.FSResolveAliasFile(alias_fp, True)[0].as_pathname()
where alias_fp is the path to the file I'm curious about, stored as a string (source).
However, the documentation cheerfully tells me that the whole Carbon family of modules is deprecated. What should I be using instead?
EDIT: I believe the code below is a step in the right direction for the PyObjC approach. It doesn't resolve aliases, but it seems to detect them.
from AppKit import NSWorkspace
def is_alias (path):
uti, err = NSWorkspace.sharedWorkspace().typeOfFile_error_(
os.path.realpath(path), None)
if err:
raise Exception(unicode(err))
else:
return "com.apple.alias-file" == uti
(source)
Unfortunately I'm not able to get @Milliways's solution working (knowing nothing about Cocoa) and stuff I find elsewhere on the internet looks far more complicated (perhaps it's handling all kinds of edge cases?).
回答1:
The PyObjC bridge lets you access NSURL's bookmark handling, which is the modern (backwards compatible) replacement for aliases:
import os.path
from Foundation import *
def target_of_alias(path):
url = NSURL.fileURLWithPath_(path)
bookmarkData, error = NSURL.bookmarkDataWithContentsOfURL_error_(url, None)
if bookmarkData is None:
return None
opts = NSURLBookmarkResolutionWithoutUI | NSURLBookmarkResolutionWithoutMounting
resolved, stale, error = NSURL.URLByResolvingBookmarkData_options_relativeToURL_bookmarkDataIsStale_error_(bookmarkData, opts, None, None, None)
return resolved.path()
def resolve_links_and_aliases(path):
while True:
alias_target = target_of_alias(path)
if alias_target:
path = alias_target
continue
if os.path.islink(path):
path = os.path.realpath(path)
continue
return path
回答2:
The following Cocoa code will resolve alias.
NSURL *targetOfAlias(NSURL *url) {
CFErrorRef *errorRef = NULL;
CFDataRef bookmark = CFURLCreateBookmarkDataFromFile (NULL, (__bridge CFURLRef)url, errorRef);
if (bookmark == nil) return nil;
CFURLRef resolvedUrl = CFURLCreateByResolvingBookmarkData (NULL, bookmark, kCFBookmarkResolutionWithoutUIMask, NULL, NULL, false, errorRef);
CFRelease(bookmark);
return CFBridgingRelease(resolvedUrl);
}
I don't know how to invoke Cocoa framework from Python, but I am sure someone has done it
The following link shows code to resolve aslias or symlink https://stackoverflow.com/a/21151368/838253
回答3:
The APIs those modules use are deprecated by Apple, it appears. You should use POSIX APIs instead.
os.path.realpath(FILE_OBJECT.name)
来源:https://stackoverflow.com/questions/21244781/what-replaces-the-now-deprecated-carbon-file-fsresolvealiasfile-in-python-on-osx