Swift 在Mac上复制文件

FileManager.default.copyItem

Posted by Joker Hook on May 18, 2022

注意

在macOS1上使用该功能需要删除App SandBox功能.

class File {
    var filename: String
    var fileExtension: String
    
    init(fileName: String, fileExtension: String) {
        self.filename = fileName
        self.fileExtension = fileExtension
    }
    
    func getFileURLString() -> String? {
        if let path = Bundle.main.path(forResource: filename, ofType: fileExtension) {
            print(path)
            return path
        }
        return nil
    }
    
    func copyFile(to dest: String, with fileName: String, with fileExtension: String) -> Bool {
        if let filePath = getFileURLString() {
            if FileManager().secureCopyItem(at: filePath, to: dest, with: fileName, with: fileExtension) {
                return true
            }
        }
        return false
    }
}

File类接受两个参数用于初始化该类: 文件名filename与文件扩展名fileExtension。类方法getFileURLString()返回需要复制的文件的原始路径,为可选值,如果该文件不存在则返回nil。类方法copyFile(to dest: String, with fileName: String, with fileExtension: String)接受三个参数,想要拷贝的路径dest,路径为完整路径,类似/Users/joker/Desktop/,文件名fileName与文件扩展名fileExtension。类方法copyFile(to dest: String, with fileName: String, with fileExtension: String)返回一个Bool结果,如果文件复制成功返回true,否则返回false

扩展类secureCopyItem(at srcPath: String, to dstPath: String, with fileName: String, with fileExtension: String) -> BoolFileManager的类扩展,其接受四个参数: 原始文件所在位置srcPath, 例如: /Users/joker/Desktop/file.txt, 拷贝路径dstPath,例如:/Users/joker/Desktop/,文件名fileName与文件扩展名fileExtension。该类方法返回一个Bool结果,如果文件复制成功返回true,否则返回false

扩展类NewTargetFileURL(filePath: String, fileName:String, fileExtension: String) -> URL?生成一个目标文件路径,例如: /Users/joker/Documents/file.txt,若该文件路径下已存在,则给文件自动创建其他命名,如/Users/joker/Documents/file 1.txt。该类方法源代码如下:

open func NewTargetFileURL(filePath: String, fileName:String, fileExtension: String) -> URL? {
        
    let fileManager = FileManager.default
        
    do {
        let contentsOfDirectory = try fileManager.contentsOfDirectory(
            at: URL(fileURLWithPath: filePath),
            includingPropertiesForKeys: nil,
            options: .skipsHiddenFiles
        )
            
        let newFileName = NewFileNameGenerator(
            fileBaseName: fileName,
            fileExtension: fileExtension
        ).makeNewFileName(for: contentsOfDirectory)
            
        let newFileURL = URL(fileURLWithPath: filePath)
            .appendingPathComponent(newFileName)
            .appendingPathExtension(fileExtension)
        return newFileURL
    } catch {
        print(error)
        return nil
    }
}

NewFileNameGenerator是一个用于生成文件名称的类,其定义如下:

public struct NewFileNameGenerator {
    
    private let fileBaseName: String
    private let fileExtension: String
    
    public init(fileBaseName: String, fileExtension: String) {
        self.fileBaseName = fileBaseName
        self.fileExtension = fileExtension
    }
    
    public func makeNewFileName(for contentsOfDirectory: [URL]) -> String {
        let existingFileURLs = contentsOfDirectory.filter({
            $0.lastPathComponent.hasPrefix(fileBaseName) && $0.pathExtension == fileExtension
        })
        
        let existingFileNames = existingFileURLs.map({ $0.deletingPathExtension().lastPathComponent })
        
        var iteration = 0
        var newFileName = fileBaseName
        
        while existingFileNames.contains(newFileName) {
            iteration += 1
            newFileName = "\(fileBaseName) \(iteration)"
        }
        
        return newFileName
    }
}

NewFileNameGenerator类接受两个参数用于初始化该类: 文件名filename与文件扩展名fileExtension。类方法makeNewFileName(for contentsOfDirectory: [URL]) -> String返回目标文件的文件名,如果该路径下文件存在,则命名将会自动添加后缀,如file 1: