Solution in 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 } } }
source share