如何在 OS X 中移动文件并创建丢失的目录?
How to move a file and create missing directories in OS X?
我想将 OSX 中的文件移动到另一个目录:
func moveFile(currentPath currentPath: String, targetPath: String) {
let fileManager = NSFileManager.defaultManager()
do { try fileManager.moveItemAtPath(currentPath, toPath: targetPath) }
catch let error as NSError { print(error.description) }
}
一切正常,除了目标目录不存在的情况。我发现 .isWritableFileAtPath
可能会有帮助。
但是,在我声明的函数中,我使用了完整的文件路径(包括文件名)。
一般情况下如何从路径或更多路径中拆分文件名:如果需要,我如何强制Swift在移动文件之前创建目录?
过去我用类似于下面代码的代码解决了这个问题。基本上,您只需检查代表您要创建的文件的父目录的路径中是否存在文件。如果它不存在,您将创建它,并在不存在的路径中创建它上面的所有文件夹。
func moveFile(currentPath currentPath: String, targetPath: String) {
let fileManager = NSFileManager.defaultManager()
let parentPath = (targetPath as NSString).stringByDeletingLastPathComponent()
var isDirectory: ObjCBool = false
if !fileManager.fileExistsAtPath(parentPath, isDirectory:&isDirectory) {
fileManager.createDirectoryAtPath(parentPath, withIntermediateDirectories: true, attributes: nil)
// Check to see if file exists, move file, error handling
}
else if isDirectory {
// Check to see if parent path is writable, move file, error handling
}
else {
// Parent path exists and is a file, error handling
}
}
您可能还想使用 fileExistsAtPath:isDirectory: 变体,以便处理其他错误情况。
也是如此
我已将此扩展添加到 FileManager
以实现此目的
extension FileManager {
func moveItemCreatingIntermediaryDirectories(at: URL, to: URL) throws {
let parentPath = to.deletingLastPathComponent()
if !fileExists(atPath: parentPath.path) {
try createDirectory(at: parentPath, withIntermediateDirectories: true, attributes: nil)
}
try moveItem(at: at, to: to)
}
}
添加这个是因为这个问题在 Google 中弹出,而其他答案使用的 API 在这种情况下可能不应该。
请务必在 FileExists(atPath:) 文档中注意这一点:
Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It’s far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed. For more information on file-system race conditions, see Race Conditions and Secure File Operations in Secure Coding Guide.
此外,来自 createDirectory(atPath:withIntermediateDirectories:attributes:) 文档:
Return Value
true if the directory was created, true if createIntermediates is set and the directory already exists, or false if an error occurred.
在 withIntermediateDirectories:
参数设置为 true 的情况下尝试创建一个新目录,如果该目录已经存在,则不会抛出错误,因此即使该目录已经存在,您也可以安全地使用它。
跳过存在检查,尝试写入目录,然后尝试移动文件:
func moveFile(from currentURL: URL, to targetURL: URL) {
// Get the target directory by removing the file component
let targetDir = targetURL.deletingLastPathComponent()
do {
try FileManager.default.createDirectory(at:targetDir, withIntermediateDirectories: true, attributes: nil)
} catch {
// Handle errors
}
do {
try FileManager.default.moveItem(at:currentURL, to: targetURL) }
catch {
// Handle errors
}
}
我想将 OSX 中的文件移动到另一个目录:
func moveFile(currentPath currentPath: String, targetPath: String) {
let fileManager = NSFileManager.defaultManager()
do { try fileManager.moveItemAtPath(currentPath, toPath: targetPath) }
catch let error as NSError { print(error.description) }
}
一切正常,除了目标目录不存在的情况。我发现 .isWritableFileAtPath
可能会有帮助。
但是,在我声明的函数中,我使用了完整的文件路径(包括文件名)。
一般情况下如何从路径或更多路径中拆分文件名:如果需要,我如何强制Swift在移动文件之前创建目录?
过去我用类似于下面代码的代码解决了这个问题。基本上,您只需检查代表您要创建的文件的父目录的路径中是否存在文件。如果它不存在,您将创建它,并在不存在的路径中创建它上面的所有文件夹。
func moveFile(currentPath currentPath: String, targetPath: String) {
let fileManager = NSFileManager.defaultManager()
let parentPath = (targetPath as NSString).stringByDeletingLastPathComponent()
var isDirectory: ObjCBool = false
if !fileManager.fileExistsAtPath(parentPath, isDirectory:&isDirectory) {
fileManager.createDirectoryAtPath(parentPath, withIntermediateDirectories: true, attributes: nil)
// Check to see if file exists, move file, error handling
}
else if isDirectory {
// Check to see if parent path is writable, move file, error handling
}
else {
// Parent path exists and is a file, error handling
}
}
您可能还想使用 fileExistsAtPath:isDirectory: 变体,以便处理其他错误情况。
也是如此我已将此扩展添加到 FileManager
以实现此目的
extension FileManager {
func moveItemCreatingIntermediaryDirectories(at: URL, to: URL) throws {
let parentPath = to.deletingLastPathComponent()
if !fileExists(atPath: parentPath.path) {
try createDirectory(at: parentPath, withIntermediateDirectories: true, attributes: nil)
}
try moveItem(at: at, to: to)
}
}
添加这个是因为这个问题在 Google 中弹出,而其他答案使用的 API 在这种情况下可能不应该。
请务必在 FileExists(atPath:) 文档中注意这一点:
Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It’s far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed. For more information on file-system race conditions, see Race Conditions and Secure File Operations in Secure Coding Guide.
此外,来自 createDirectory(atPath:withIntermediateDirectories:attributes:) 文档:
Return Value
true if the directory was created, true if createIntermediates is set and the directory already exists, or false if an error occurred.
在 withIntermediateDirectories:
参数设置为 true 的情况下尝试创建一个新目录,如果该目录已经存在,则不会抛出错误,因此即使该目录已经存在,您也可以安全地使用它。
跳过存在检查,尝试写入目录,然后尝试移动文件:
func moveFile(from currentURL: URL, to targetURL: URL) {
// Get the target directory by removing the file component
let targetDir = targetURL.deletingLastPathComponent()
do {
try FileManager.default.createDirectory(at:targetDir, withIntermediateDirectories: true, attributes: nil)
} catch {
// Handle errors
}
do {
try FileManager.default.moveItem(at:currentURL, to: targetURL) }
catch {
// Handle errors
}
}