6

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

編集: 両方の答えが正しいです!コードが 10.9 で実行され、より柔軟になるという要件が最初に述べられていなかったため、mklement0 の回答を選択します。

4

4 に答える 4

5

を使った解決法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
}

スウィフト 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
}

関数がサンドボックス環境で呼び出される場合は、適切な資格を提供するように注意してください。

于 2015-10-26T15:21:00.930 に答える
4

vadian の回答は、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 のソリューションでは、サンドボックス化されたアプリケーション/環境で関数を使用するために適切な資格が必要です。vadianのソリューションとは異なり、 Xcode Playgroundで実行されるため、これは少なくとも同じ程度には必要ないようです。誰かがこれに光を当てることができれば、助けてください。

    • ただし、どちらのソリューションも、shebang line を使用してシェル スクリプトで実行されます#!/usr/bin/env swift
  • 特定のパスが Finder エイリアスであるかどうかを明示的にテストする場合は、vadian から派生したこの回答を参照してください。

于 2015-10-27T06:04:45.563 に答える
1

主にvadianのアプローチに基づいたSwift 3の実装を次に示します。私の考えは、ファイルの URL を返すことなので、効果的にfileURLWithPath. 既存の Objective-C コードから呼び出せるようにする必要があるため、これは NSURL クラス拡張です。

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
    }
}
于 2017-03-15T16:36:42.400 に答える