2013-09-27 15 views
6

Fondamentalmente sto cercando un modo per unire due cartelle nel file system con l'API di cacao:Unire cartelle con NSFileManager, sovrascrivere solo i file esistenti

Ho una cartella contenente i file e sottocartelle, che voglio copiare in una posizione diversa nel filesystem.
Nel percorso di destinazione, esiste già una cartella con lo stesso nome, che può contenere anche file e cartelle.

Ora voglio sovrascrivere i file esistenti nella mia cartella di destinazione (o nelle sue sottocartelle) con il nuovo contenuto della mia cartella di origine se hanno lo stesso nome.
Tutti gli altri file che voglio lasciare intatti.

sourcefolder 
    | 
    - file1 
    - subfolder 
     - file2 


destinationfolder 
    | 
    - file3 
    - subfolder 
     - file2 
     - file4 


resultingfolder 
    | 
    - file1 
    - file3 
    - subfolder 
     - file2  <-- version from source folder 
     - file4 

Come posso farlo? Grazie mille per il tuo aiuto!

risposta

7

Ho cercato ovunque ma non ho trovato nulla. Così ho trovato la mia soluzione, utilizzando NSDirectoryEnumerator. Questo dovrebbe funzionare nel diagramma (sovrascrivendo i vecchi file). Spero che sia d'aiuto.

- (void)mergeContentsOfPath:(NSString *)srcDir intoPath:(NSString *)dstDir error:(NSError**)err { 

    NSLog(@"- mergeContentsOfPath: %@\n intoPath: %@", srcDir, dstDir); 

    NSFileManager *fm = [NSFileManager defaultManager]; 
    NSDirectoryEnumerator *srcDirEnum = [fm enumeratorAtPath:srcDir]; 
    NSString *subPath; 
    while ((subPath = [srcDirEnum nextObject])) { 

     NSLog(@" subPath: %@", subPath); 
     NSString *srcFullPath = [srcDir stringByAppendingPathComponent:subPath]; 
     NSString *potentialDstPath = [dstDir stringByAppendingPathComponent:subPath]; 

     // Need to also check if file exists because if it doesn't, value of `isDirectory` is undefined. 
     BOOL isDirectory = ([[NSFileManager defaultManager] fileExistsAtPath:srcFullPath isDirectory:&isDirectory] && isDirectory); 

     // Create directory, or delete existing file and move file to destination 
     if (isDirectory) { 
      NSLog(@" create directory"); 
      [fm createDirectoryAtPath:potentialDstPath withIntermediateDirectories:YES attributes:nil error:err]; 
      if (err && *err) { 
       NSLog(@"ERROR: %@", *err); 
       return; 
      } 
     } 
     else { 
      if ([fm fileExistsAtPath:potentialDstPath]) { 
       NSLog(@" removeItemAtPath"); 
       [fm removeItemAtPath:potentialDstPath error:err]; 
       if (err && *err) { 
        NSLog(@"ERROR: %@", *err); 
        return; 
       } 
      } 

      NSLog(@" moveItemAtPath"); 
      [fm moveItemAtPath:srcFullPath toPath:potentialDstPath error:err]; 
      if (err && *err) { 
       NSLog(@"ERROR: %@", *err); 
       return; 
      } 
     } 
    } 
} 
+0

Il metodo '' enumeratorAtPath funziona così grande. –

+0

Sei fantastico !!! Mi ha risparmiato un sacco di tempo :) – jj080808

1

Guarda i metodi del gestore di file e invece di utilizzare il file manager di default, creare il proprio con alloc/init, impostare un delegato, e utilizzare i metodi delegato.

+0

Grazie per il suggerimento! Ho anche scoperto da solo che ci sono altri metodi che possono farlo in modo più pulito. Modificherò la mia risposta. – Hlung

2

Una soluzione a Swift 3

let merger = FoldersMerger(actionType: .copy, conflictResolution: .keepSource) 
merger.merge(atPath: sourceFolder, toPath: destinationFolder) 


class FoldersMerger { 

    enum ActionType { case move, copy } 
    enum ConflictResolution { case keepSource, keepDestination } 

    private let fileManager = FileManager() 
    private var actionType: ActionType! 
    private var conflictResolution: ConflictResolution! 
    private var deleteEmptyFolders: Bool! 

    init(actionType: ActionType = .move, conflictResolution: ConflictResolution = .keepDestination, deleteEmptyFolders: Bool = false) { 
     self.actionType = actionType 
     self.conflictResolution = conflictResolution 
     self.deleteEmptyFolders = deleteEmptyFolders 
    } 

    func merge(atPath: String, toPath: String) { 
     let pathEnumerator = fileManager.enumerator(atPath: atPath) 

     var folders: [String] = [atPath] 

     while let relativePath = pathEnumerator?.nextObject() as? String { 

      let subItemAtPath = URL(fileURLWithPath: atPath).appendingPathComponent(relativePath).path 
      let subItemToPath = URL(fileURLWithPath: toPath).appendingPathComponent(relativePath).path 

      if isDir(atPath: subItemAtPath) { 

       if deleteEmptyFolders! { 
        folders.append(subItemAtPath) 
       } 

       if !isDir(atPath: subItemToPath) { 
        do { 
         try fileManager.createDirectory(atPath: subItemToPath, withIntermediateDirectories: true, attributes: nil) 
         NSLog("FoldersMerger: directory created: %@", subItemToPath) 
        } 
        catch let error { 
         NSLog("ERROR FoldersMerger: %@", error.localizedDescription) 
        } 
       } 
       else { 
        NSLog("FoldersMerger: directory %@ already exists", subItemToPath) 
       } 
      } 
      else { 

       if isFile(atPath:subItemToPath) && conflictResolution == .keepSource { 
        do { 
         try fileManager.removeItem(atPath: subItemToPath) 
         NSLog("FoldersMerger: file deleted: %@", subItemToPath) 
        } 
        catch let error { 
         NSLog("ERROR FoldersMerger: %@", error.localizedDescription) 
        } 
       } 

       do { 
        try fileManager.moveItem(atPath: subItemAtPath, toPath: subItemToPath) 
        NSLog("FoldersMerger: file moved from %@ to %@", subItemAtPath, subItemToPath) 
       } 
       catch let error { 
        NSLog("ERROR FoldersMerger: %@", error.localizedDescription) 
       } 
      } 
     } 

     if deleteEmptyFolders! { 
      folders.sort(by: { (path1, path2) -> Bool in 
       return path1.characters.split(separator: "/").count < path2.characters.split(separator: "/").count 
      }) 
      while let folderPath = folders.popLast() { 
       if isDirEmpty(atPath: folderPath) { 
        do { 
         try fileManager.removeItem(atPath: folderPath) 
         NSLog("FoldersMerger: empty dir deleted: %@", folderPath) 
        } 
        catch { 
         NSLog("ERROR FoldersMerger: %@", error.localizedDescription) 
        } 
       } 
      } 
     } 
    } 

    private func isDir(atPath: String) -> Bool { 
     var isDir: ObjCBool = false 
     let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir) 
     return exist && isDir.boolValue 
    } 

    private func isFile(atPath: String) -> Bool { 
     var isDir: ObjCBool = false 
     let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir) 
     return exist && !isDir.boolValue 
    } 

    private func isDirEmpty(atPath: String) -> Bool { 
     do { 
      return try fileManager.contentsOfDirectory(atPath: atPath).count == 0 
     } 
     catch _ { 
      return false 
     } 
    } 
} 
Problemi correlati