import Foundation public extension URL { static var cwd: URL { FileManager.default.currentDirectoryPath.url(directoryHint: .isDirectory) } var filepath: String { withUnsafeFileSystemRepresentation { String(cString: $0!) } } var isSwiftFile: Bool { isFile && pathExtension == "swift" } var isFile: Bool { var isDirectoryObjC: ObjCBool = false if FileManager.default.fileExists(atPath: filepath, isDirectory: &isDirectoryObjC) { return !isDirectoryObjC.boolValue } return false } var isDirectory: Bool { var isDirectoryObjC: ObjCBool = false if FileManager.default.fileExists(atPath: filepath, isDirectory: &isDirectoryObjC) { return isDirectoryObjC.boolValue } return false } /// Path relative to the current working directory. /// /// > Warning: Use this representation only for displaying file paths to users. It is not /// suitable for file operations. var relativeDisplayPath: String { let path = path.replacing(Self.cwd.path, with: "") if path.starts(with: "/") { return String(path.dropFirst()) } return path } var exists: Bool { isFileURL && FileManager.default.fileExists(atPath: filepath) } func relative(to base: URL) -> URL { guard base.isFileURL, isFileURL else { return self } let baseComponents = base.standardizedFileURL.pathComponents let selfComponents = standardizedFileURL.pathComponents var index = 0 while index < baseComponents.count, index < selfComponents.count, baseComponents[index] == selfComponents[index] { index += 1 } var newPath = base for _ in index.. URL { guard var base else { return URL(filePath: self, directoryHint: directoryHint).standardizedFileURL } if base.isDirectory { let lastComponent = base.lastPathComponent base.deleteLastPathComponent() base.append(path: lastComponent, directoryHint: .isDirectory) } return URL(filePath: self, directoryHint: directoryHint, relativeTo: base).standardizedFileURL } }