Macos 获取swift中文件的别名路径
我在解析mac上的别名链接时遇到问题。我正在检查该文件是否为别名,然后希望接收原始路径。相反,我只得到一个文件Id。 有什么好主意Macos 获取swift中文件的别名路径,macos,swift,cfurl-encoding,Macos,Swift,Cfurl Encoding,我在解析mac上的别名链接时遇到问题。我正在检查该文件是否为别名,然后希望接收原始路径。相反,我只得到一个文件Id。 有什么好主意 func isFinderAlias(path:String) -> Bool? { var isAlias:Bool? = false // Initialize result var. // Create a CFURL instance for the given filesystem path. // This should
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
}
func-isFinderAlias(路径:String)->Bool?{
var isAlias:Bool?=false//初始化结果变量。
//为给定的文件系统路径创建一个CFURL实例。
//这永远不会失败,因为在这一点上还没有验证存在性。
//注意:以后无需调用CFRelease(fUrl),因为Swift auto memory管理CoreFoundation对象。
打印(“路径之前的路径\(路径)”);
设fUrl=cfurlCreateWithFileSystemStyle(nil,path,CFURLPathStyle.CFURLPOSIXPathStyle,false)
打印(“路径卷曲\(卷曲)”;
//分配空指针-无需初始化,
//它将由下面的cfurlCopyResourcePropertyWorkey()分配给。
设ptrPropVal=unsafemeutablepointer.alloc(1)
//调用CoreFoundation函数,将所需信息复制为
//返回时prt将指向的新分配内存的CFBoolean。
如果cfurlcopyresourcePropertyWorkey(fUrl、kCFURLIsAliasFileKey、ptrPropVal、nil){
//从分配的内存中提取Bool值。
isAlias=UnsafePointer(ptrPropVal)。内存为Bool
//它将由下面的cfurlCopyResourcePropertyWorkey()分配给。
设ptrDarwin=unsafemeutablepointer.alloc(1)
如果((isAlias)=真){
如果let bookmark=CFURLCreateBookmarkDataFromFile(kcfalocatordefault,fUrl,nil){
设url=CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault,bookmark.takeRetainedValue(),CFURLBookmarkResolutionOptions.CFBookmarkResolutionWithoutMountingMask,nil,nil,ptrDarwin,nil)
打印(“获取路径\(url)”)
}
}
//由于CF*()调用包含“Copy”一词,因此我们对此负责
//为了破坏(释放)记忆。
ptrDarwin.destroy()
ptrDarwin.dealloc(1)
ptrPropVal.destroy()
}
//取消分配指针
ptrPropVal.dealloc(1)
回归伊萨利亚斯
}
编辑:
两个答案都是正确的!
我会选择mklement0的答案,因为最初没有说明代码在10.9上运行的要求,这使得它更加灵活这是一个使用
NSURL
的解决方案
它需要一个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:
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
}
如果在沙盒环境中调用该函数,请注意提供适当的权限。在OS X 10.10+上非常有效
下面是一个同样适用于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
}
注:
- 与vadian的解决方案不同,即使对于非别名文件,也会返回一个值,即该文件自己的完整路径,并将路径字符串而不是
实例作为输入NSURL
- vadian的解决方案需要适当的权限,以便在沙盒应用程序/环境中使用该功能。看起来这一个至少不需要达到同样的程度,因为它将在Xcode操场上运行,不像瓦迪安的解决方案。如果有人能说明这一点,请帮助
- 然而,这两种解决方案都在shebang行
#的shell脚本中运行/usr/bin/env swift
- 然而,这两种解决方案都在shebang行
- 如果要显式测试给定路径是否为查找器别名,请参阅,它是从vadian的派生而来的,但由于其焦点较窄,因此也在10.9上运行
- 这是一个Swift 3实现,主要基于瓦迪安的方法。我的想法是返回一个文件URL,因此我将它与
fileURLWithPath
有效地结合起来。这是一个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变量我需要返回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
}
是否有理由使用核心基金而不是基金会(即代码> NSURL)?如何用基础的有趣的解决方案来检查别名?但是NSURLBookmarkResolutionOptions在10.10上不可用,或者新的(获取错误消息)也由ResolvingAliasFileAttribute无法使用10.10之前的版本,是吗?
NSURLBookmarkResolutionOptions
自10.6起可用,NSURL(ByResolvingAliasFileAttribute:options:)
自10日起提供。10@Silve2611:也许您只是忘记了导入基础?很好的解决方案;请注意,Xcode操场显然也有沙盒,因此您不能在那里尝试该功能,但它确实可以从带有shebang line#的脚本中工作/usr/bin/env swift
。传递[nsurlbookmarksolutionoptions.WithoutUI,nsurlbookmarksolutionoptions.WithoutMounting]
而不是nsurlbookmarksolutionoptions()
;奎布尔:由于函数返回类型String?
,因此使用没有意义中的code>返回原始路径代码>伟大的解决方案。我把它标记为正确的。但如果有人能以10.9美元的价格展示如何做到这一点,那就太好了。我马上就要到了,我会继续努力的。谢谢你提供的伟大解决方案!你帮了我很多!不幸的是,我已经将一个答案标记为正确,因为它是一个有效的解决方案。这个解决方案甚至更好@Silve2611很高兴听到这个消息;请至少投票给瓦迪安的答案,并在你的问题中说明你选择这个答案是因为最初没有说明代码也运行在10.9上的要求。