[英]Getting alias path of file in swift
I'm having trouble resolving the alias link on mac. 我在解析Mac上的别名链接时遇到问题。 I'm checking if the file is an alias and then I would want to receive the original path.
我正在检查文件是否为别名,然后要接收原始路径。 Instead I'm only getting a File-Id.
相反,我只得到一个文件ID。 Anly ideas?
安莉的想法?
func isFinderAlias(path:String) -> Bool? {
var isAlias:Bool? = false // Initialize result var.
// Create a CFURL instance for the given filesystem path.
// This should never fail, because the existence isn't verified at this point.
// Note: No need to call CFRelease(fUrl) later, because Swift auto-memory-manages CoreFoundation objects.
print("path before \(path)");
let fUrl = CFURLCreateWithFileSystemPath(nil, path, CFURLPathStyle.CFURLPOSIXPathStyle, false)
print("path furl \(fUrl)");
// Allocate void pointer - no need for initialization,
// it will be assigned to by CFURLCopyResourcePropertyForKey() below.
let ptrPropVal = UnsafeMutablePointer<Void>.alloc(1)
// Call the CoreFoundation function that copies the desired information as
// a CFBoolean to newly allocated memory that prt will point to on return.
if CFURLCopyResourcePropertyForKey(fUrl, kCFURLIsAliasFileKey, ptrPropVal, nil) {
// Extract the Bool value from the memory allocated.
isAlias = UnsafePointer<CFBoolean>(ptrPropVal).memory as Bool
// it will be assigned to by CFURLCopyResourcePropertyForKey() below.
let ptrDarwin = UnsafeMutablePointer<DarwinBoolean>.alloc(1)
if ((isAlias) == true){
if let bookmark = CFURLCreateBookmarkDataFromFile(kCFAllocatorDefault, fUrl, nil){
let url = CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, bookmark.takeRetainedValue(), CFURLBookmarkResolutionOptions.CFBookmarkResolutionWithoutMountingMask, nil, nil, ptrDarwin, nil)
print("getting the path \(url)")
}
}
// Since the CF*() call contains the word "Copy", WE are responsible
// for destroying (freeing) the memory.
ptrDarwin.destroy()
ptrDarwin.dealloc(1)
ptrPropVal.destroy()
}
// Deallocate the pointer
ptrPropVal.dealloc(1)
return isAlias
}
EDIT: Both Answers are correct! 编辑:两个答案都是正确的! I would choose the answer of mklement0 due to the originally not stated requirement that the code run on 10.9 which makes it more flexible
我之所以选择mklement0的答案,是因为最初没有说明该代码必须在10.9上运行,这使其更加灵活
This is a solution using NSURL
. 这是使用
NSURL
的解决方案。
It expects an NSURL
object as parameter and returns either the original path if the url is an alias or nil
. 它期望使用
NSURL
对象作为参数,如果url是别名或nil
,则返回原始路径。
func resolveFinderAlias(url:NSURL) -> String? {
var isAlias : AnyObject?
do {
try url.getResourceValue(&isAlias, forKey: NSURLIsAliasFileKey)
if isAlias as! Bool {
do {
let original = try NSURL(byResolvingAliasFileAtURL: url, options: NSURLBookmarkResolutionOptions())
return original.path!
} catch let error as NSError {
print(error)
}
}
} catch _ {}
return nil
}
Swift 3: 斯威夫特3:
func resolveFinderAlias(at url: URL) -> String? {
do {
let resourceValues = try url.resourceValues(forKeys: [.isAliasFileKey])
if resourceValues.isAliasFile! {
let original = try URL(resolvingAliasFileAt: url)
return original.path
}
} catch {
print(error)
}
return nil
}
Be aware to provide appropriate entitlements if the function is called in a sandboxed environment. 如果在沙盒环境中调用该函数,请注意提供适当的权利。
vadian's answer works great on OS X 10.10+ . vadian的答案在OS X 10.10+上效果很好。
Here's an implementation that also works on OS X 10.9 : 这是在OS X 10.9上也可以使用的实现 :
// OSX 10.9+
// Resolves a Finder alias to its full target path.
// If the given path is not a Finder alias, its *own* full path is returned.
// If the input path doesn't exist or any other error occurs, nil is returned.
func resolveFinderAlias(path: String) -> String? {
let fUrl = NSURL(fileURLWithPath: path)
var targetPath:String? = nil
if (fUrl.fileReferenceURL() != nil) { // item exists
do {
// Get information about the file alias.
// If the file is not an alias files, an exception is thrown
// and execution continues in the catch clause.
let data = try NSURL.bookmarkDataWithContentsOfURL(fUrl)
// NSURLPathKey contains the target path.
let rv = NSURL.resourceValuesForKeys([ NSURLPathKey ], fromBookmarkData: data)
targetPath = rv![NSURLPathKey] as! String?
} catch {
// We know that the input path exists, but treating it as an alias
// file failed, so we assume it's not an alias file and return its
// *own* full path.
targetPath = fUrl.path
}
}
return targetPath
}
Note: 注意:
Unlike vadian's solution, this will return a value even for non -alias files, namely that file's own full path, and takes a path string rather than a NSURL
instance as input. 与vadian的解决方案不同,这甚至会为非别名文件返回一个值,即该文件自己的完整路径,并以路径字符串而不是
NSURL
实例作为输入。
vadian's solution requires appropriate entitlements in order to use the function in a sandboxed application/environment. vadian的解决方案需要适当的权利,以便在沙盒应用程序/环境中使用该功能。 It seems that this one at least doesn't need that to the same extent , as it will run in an Xcode Playground , unlike vadian's solution.
看来 ,这一次至少不需要那么在相同的程度 ,因为它会在一个Xcode游乐场运行,不像vadian的解决方案。 If someone can shed light on this, please help.
如果有人可以阐明这一点,请帮助。
#!/usr/bin/env swift
. #!/usr/bin/env swift
的shell脚本 中运行。 If you want to explicitly test whether a given path is a Finder alias, see this answer , which is derived from vadian's, but due to its narrower focus also runs on 10.9. 如果要显式测试给定路径是否为Finder别名,请参见此答案 , 该答案是从vadian派生的,但由于它的关注范围更窄,因此也适用于10.9。
Here's a Swift 3 implementation, based largely on vadian's approach. 这是一个Swift 3实现,主要基于vadian的方法。 My idea is to return a file URL, so I effectively combine it with
fileURLWithPath
. 我的想法是返回文件URL,因此我将其与
fileURLWithPath
有效地结合在一起。 It's an NSURL class extension because I need to be able to call into it from existing Objective-C code: 这是一个NSURL类扩展,因为我需要能够从现有的Objective-C代码中对其进行调用:
extension NSURL {
class func fileURL(path:String, resolveAlias yn:Bool) -> URL {
let url = URL(fileURLWithPath: path)
if !yn {
return url
}
do {
let vals = try url.resourceValues(forKeys: [.isAliasFileKey])
if let isAlias = vals.isAliasFile {
if isAlias {
let original = try URL(resolvingAliasFileAt: url)
return original
}
}
} catch {
return url // give up
}
return url // really give up
}
}
URL variant I need to return nil (not an alias or error) else original - Swift4 URL变体,我需要返回nil(不是别名或错误),否则将是原始的-Swift4
func resolvedFinderAlias() -> URL? {
if (self.fileReferenceURL() != nil) { // item exists
do {
// Get information about the file alias.
// If the file is not an alias files, an exception is thrown
// and execution continues in the catch clause.
let data = try NSURL.bookmarkData(withContentsOf: self as URL)
// NSURLPathKey contains the target path.
let rv = NSURL.resourceValues(forKeys: [ URLResourceKey.pathKey ], fromBookmarkData: data)
var urlString = rv![URLResourceKey.pathKey] as! String
if !urlString.hasPrefix("file://") {
urlString = "file://" + urlString
}
return URL.init(string: urlString)
} catch {
// We know that the input path exists, but treating it as an alias
// file failed, so we assume it's not an alias file so return nil.
return nil
}
}
return nil
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.