2016-07-13 22 views

cevap

17

İşte URL için bir uzantısı almak için yöntemler seti, liste ile olarak Swift 3 olası bir uygulamasıdır ve bir dosya genişletilmiş özelliklerini kaldırın. (Swift 2 kod aşağıda bulunabilir.)

extension URL { 

    /// Get extended attribute. 
    func extendedAttribute(forName name: String) throws -> Data { 

     let data = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> Data in 

      // Determine attribute size: 
      let length = getxattr(fileSystemPath, name, nil, 0, 0, 0) 
      guard length >= 0 else { throw URL.posixError(errno) } 

      // Create buffer with required size: 
      var data = Data(count: length) 

      // Retrieve attribute: 
      let result = data.withUnsafeMutableBytes { 
       getxattr(fileSystemPath, name, $0, data.count, 0, 0) 
      } 
      guard result >= 0 else { throw URL.posixError(errno) } 
      return data 
     } 
     return data 
    } 

    /// Set extended attribute. 
    func setExtendedAttribute(data: Data, forName name: String) throws { 

     try self.withUnsafeFileSystemRepresentation { fileSystemPath in 
      let result = data.withUnsafeBytes { 
       setxattr(fileSystemPath, name, $0, data.count, 0, 0) 
      } 
      guard result >= 0 else { throw URL.posixError(errno) } 
     } 
    } 

    /// Remove extended attribute. 
    func removeExtendedAttribute(forName name: String) throws { 

     try self.withUnsafeFileSystemRepresentation { fileSystemPath in 
      let result = removexattr(fileSystemPath, name, 0) 
      guard result >= 0 else { throw URL.posixError(errno) } 
     } 
    } 

    /// Get list of all extended attributes. 
    func listExtendedAttributes() throws -> [String] { 

     let list = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> [String] in 
      let length = listxattr(fileSystemPath, nil, 0, 0) 
      guard length >= 0 else { throw URL.posixError(errno) } 

      // Create buffer with required size: 
      var data = Data(count: length) 

      // Retrieve attribute list: 
      let result = data.withUnsafeMutableBytes { 
       listxattr(fileSystemPath, $0, data.count, 0) 
      } 
      guard result >= 0 else { throw URL.posixError(errno) } 

      // Extract attribute names: 
      let list = data.split(separator: 0).flatMap { 
       String(data: Data($0), encoding: .utf8) 
      } 
      return list 
     } 
     return list 
    } 

    /// Helper function to create an NSError from a Unix errno. 
    private static func posixError(_ err: Int32) -> NSError { 
     return NSError(domain: NSPOSIXErrorDomain, code: Int(err), 
         userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))]) 
    } 
} 

Örnek kullanım: Swift 2 :)

Basit örneğin

let fileURL = URL(fileURLWithPath: "/path/to/file") 

let attr1 = "com.myCompany.myAttribute" 
let attr2 = "com.myCompany.otherAttribute" 

let data1 = Data(bytes: [1, 2, 3, 4]) 
let data2 = Data(bytes: [5, 6, 7, 8, 9]) 

do { 
    // Set attributes: 
    try fileURL.setExtendedAttribute(data: data1, forName: attr1) 
    try fileURL.setExtendedAttribute(data: data2, forName: attr2) 

    // List attributes: 
    let list = try fileURL.listExtendedAttributes() 
    print(list) 
    // ["com.myCompany.myAttribute", "com.myCompany.otherAttribute", "other"] 

    let data1a = try fileURL.extendedAttribute(forName: attr1) 
    print(data1a as NSData) 
    // <01020304> 

    // Remove attributes 
    for attr in list { 
     try fileURL.removeExtendedAttribute(forName: attr) 
    } 

} catch let error { 
    print(error.localizedDescription) 
} 

(Önceki cevap:

let fileURL = NSURL(fileURLWithPath: "/path/to/file") 
let attrName = "com.myCompany.myAttribute" 
var attrData: [UInt8] = [1, 2, 3, 4, 5] 

// Get local file system path: 
var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) 
guard fileURL.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { 
    fatalError("Invalid file URL") 
} 

// Set extended attribute (returns 0 on success): 
guard setxattr(&fileSystemPath, attrName, &attrData, attrData.count, 0, 0) == 0 else { 
    perror("setxattr") // prints error message of last system call 
    fatalError() 
} 

komut satırında sonucu doğrulayın:

extension NSURL { 
    // Get extended attribute. Returns `nil` on failure. 
    func extendedAttribute(forName name: String) -> [UInt8]? { 
     // Get local file system path: 
     var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) 
     guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { 
      return nil 
     } 
     // Determine attribute size: 
     let length = getxattr(fileSystemPath, name, nil, 0, 0, 0) 
     guard length >= 0 else { return nil } 
     // Create buffer with required size: 
     var data = [UInt8](count: length, repeatedValue: 0) 
     // Retrieve attribute: 
     let result = getxattr(fileSystemPath, name, &data, data.count, 0, 0) 
     guard result >= 0 else { return nil } 
     return data 
    } 

    // Set extended attribute. Returns `true` on success and `false` on failure. 
    func setExtendedAttribute(data: [UInt8], forName name: String) -> Bool { 
     // Get local file system path: 
     var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) 
     guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { 
      return false 
     } 
     // Set attribute: 
     let result = data.withUnsafeBufferPointer { 
      setxattr(fileSystemPath, name, $0.baseAddress, data.count, 0, 0) 
     } 
     return result == 0 
    } 

    // Remove extended attribute. Returns `true` on success and `false` on failure. 
    func removeExtendedAttribute(forName name: String) -> Bool { 
     // Get local file system path: 
     var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) 
     guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { 
      return false 
     } 
     // Remove attribute: 
     let result = removexattr(fileSystemPath, name, 0) 
     return result == 0 
    } 
} 

Örnek kullanım:

let fileURL = NSURL(fileURLWithPath: "/path/to/file") 
let attrName = "com.myCompany.myAttribute" 

// Set attribute: 
let data1: [UInt8] = [1, 2, 3, 4] 
fileURL.setExtendedAttribute(data1, forName: attrName) 

// Get attribute: 
if let data2 = fileURL.extendedAttribute(forName: attrName) { 
    print(data2) 
} 

// Remove attribute: 
fileURL.removeExtendedAttribute(forName: attrName) 
,

 
$ xattr -px com.myCompany.myAttribute /path/to/file 
01 02 03 04 05 

Ve burada olsun ve dosya özelliklerini ayarlayabilirsiniz nasıl NSURL uzantısı yöntemleri olarak uygulanan

+0

Cevabınız için teşekkürler. Sadece kodunuzu yapıştırdım ve uygulamayı çalıştırdım. Hata yazdırılmadı, ancak komut satırından belirlenen özniteliği doğrulayamadım. "No such xattr: com.myCompany.myAttribute" hatası var – prabhu

+0

@prabhu: Koddaki öznitelik adının komut satırındaki öznitelik adıyla aynı olduğunu iki kez kontrol ettiniz mi? Xattr/path/to/file 'ile dosyanın tüm mevcut özelliklerini listeleyebilirsiniz. - Benim için çalıştı, ben göndermeden önce kodu test ettim :) –

+0

evet senin örneğindeki gibi aynı. Hiçbir şey eksik olduğumdan emin değilim. Ama sadece postaladığın her şeyi yapıştırdım. Değişiklik yok – prabhu

0

Swift'de bir çözüm istediğini anlıyorum. Bununla birlikte, bazı insanlar melez Swift/ObjC projesine sahip olabilir veya sahip olmak isteyebilirler. Benim durumumda, bu görev için Objective-C'yi kullanmak çok daha kolaydı.

#import <Foundation/Foundation.h> 

@interface TagSetter: NSObject 
+ (BOOL)setTags:(NSArray *)tags onURL:(NSURL *)url; 
@end 

@implementation TagSetter 

+ (BOOL)setTags:(NSArray *)tags onURL:(NSURL *)url 
{ 
    NSError *error; 

    BOOL returnValue = [url setResourceValue:tags forKey:NSURLTagNamesKey error:&error]; 
    if (!returnValue) { 
     NSLog(@"ERROR: Failed setting tags '%@' on URL '%@': %@", tags, url, error); 
    } 

    return returnValue; 
} 

@end 

Bu kod GitHub'dan jdberry ile tag(1) command line tool uyarlanmıştır. Sonra using ObjC in Swift için talimatları takip ve köprü başlığına yukarıda .m dosyasını ekledi: Nihayet

#import "TagSetter.m" 

, ben Swift kodu yapmanız gereken tek şey:

TagSetter.setTags(tagNames, on:url) 

Eğer isterseniz başarısızlığa cevap verebilirsin, yapabilirsin.

Bu yaklaşımın, hafifçe hacky veya korkunç aşırı sıkıntısı varsa, basit olup olmadığını size kalmış. Ama kesinlikle çalışıyor ve sadece tek bir Swift hattıyla sonuçlanıyor.

İlgili konular