import Foundation extension URL { func ensureParentFolderExistence() throws { try deletingLastPathComponent().ensureFolderExistence() } func ensureFolderExistence() throws { guard !exists else { return } try FileManager.default.createDirectory(at: self, withIntermediateDirectories: true) } var isDirectory: Bool { do { let resources = try resourceValues(forKeys: [.isDirectoryKey]) guard let isDirectory = resources.isDirectory else { print("No isDirectory info for \(path)") return false } return isDirectory } catch { print("Failed to get directory information from \(path): \(error)") return false } } var exists: Bool { FileManager.default.fileExists(atPath: path) } /** Delete the file at the url. */ func delete() throws { try FileManager.default.removeItem(at: self) } func copy(to url: URL) throws { if url.exists { try url.delete() } try url.ensureParentFolderExistence() try FileManager.default.copyItem(at: self, to: url) } var size: Int? { let attributes = try? FileManager.default.attributesOfItem(atPath: path) return (attributes?[.size] as? NSNumber)?.intValue } func resolvingFolderTraversal() -> URL? { var components = [String]() absoluteString.components(separatedBy: "/").forEach { part in if part == ".." { if !components.isEmpty { _ = components.dropLast() } else { components.append("..") } return } if part == "." { return } components.append(part) } return URL(string: components.joined(separator: "/")) } }