{"id":1116,"url":"https://github.com/nvzqz/FileKit","last_synced_at":"2025-08-06T13:32:39.098Z","repository":{"id":47096302,"uuid":"41773162","full_name":"nvzqz/FileKit","owner":"nvzqz","description":"Simple and expressive file management in Swift","archived":false,"fork":false,"pushed_at":"2024-04-09T03:20:24.000Z","size":4878,"stargazers_count":2319,"open_issues_count":14,"forks_count":206,"subscribers_count":42,"default_branch":"develop","last_synced_at":"2024-05-01T13:15:06.771Z","etag":null,"topics":["files","paths","swift"],"latest_commit_sha":null,"homepage":"https://nvzqz.github.io/FileKit/docs/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nvzqz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"Support/Info.plist","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-02T01:45:48.000Z","updated_at":"2024-06-18T12:29:30.216Z","dependencies_parsed_at":"2024-06-18T12:29:29.038Z","dependency_job_id":"1f380c63-16d0-4198-81b1-e26bc035e30c","html_url":"https://github.com/nvzqz/FileKit","commit_stats":{"total_commits":376,"total_committers":13,"mean_commits":"28.923076923076923","dds":"0.19414893617021278","last_synced_commit":"9006d2888025fbe893c3c396327b2fe45a8c177b"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2FFileKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2FFileKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2FFileKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvzqz%2FFileKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nvzqz","download_url":"https://codeload.github.com/nvzqz/FileKit/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":215041443,"owners_count":15820364,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["files","paths","swift"],"created_at":"2024-01-05T20:15:39.256Z","updated_at":"2024-08-17T16:30:50.518Z","avatar_url":"https://github.com/nvzqz.png","language":"Swift","funding_links":["https://www.patreon.com/nvzqz","https://www.paypal.me/nvzqz"],"categories":["Files","Libs","Data and Storage","Files [🔝](#readme)"],"sub_categories":["Getting Started","Files","Other free courses","Linter","Data Management"],"readme":"\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/nvzqz/FileKit/raw/assets/banner.png\"\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/platform-osx%20%7C%20ios%20%7C%20watchos%20%7C%20tvos-lightgrey.svg\"\n         alt=\"Platform\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/language-swift-orange.svg\"\n         alt=\"Language: Swift\"\u003e\n    \u003ca href=\"https://cocoapods.org/pods/FileKit\"\u003e\n        \u003cimg src=\"https://img.shields.io/cocoapods/v/FileKit.svg\"\n             alt=\"CocoaPods\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\"\n             alt=\"Carthage\"\u003e\n    \u003c/a\u003e\n    \u003cbr\u003e\n    \u003cimg src=\"https://img.shields.io/cocoapods/dt/FileKit.svg\"\n         alt=\"downloads\"\u003e\n    \u003ca href=\"https://trello.com/b/s1MOyp2h/filekit\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Trello-filekit-blue.svg\"\n             alt=\"Trello Board\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://gitter.im/nvzqz/FileKit?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/GITTER-join%20chat-00D06F.svg\"\n             alt=\"GITTER: join chat\"\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-000000.svg\"\n         alt=\"License\"\u003e\n    \u003cbr\u003e\n    \u003ca href=\"https://www.patreon.com/nvzqz\"\u003e\n        \u003cimg src=\"https://c5.patreon.com/external/logo/become_a_patron_button.png\" alt=\"Become a Patron!\" height=\"35\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.paypal.me/nvzqz\"\u003e\n        \u003cimg src=\"https://buymecoffee.intm.org/img/button-paypal-white.png\" alt=\"Buy me a coffee\" height=\"35\"\u003e\n    \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\n  • \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\n  • \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n  • \u003ca href=\"https://nvzqz.github.io/FileKit/docs/\"\u003eDocumentation\u003c/a\u003e\n\u003c/div\u003e\n\n\nFileKit is a Swift framework that allows for simple and expressive file management.\n\nDevelopment happens in the\n[`develop`](https://github.com/nvzqz/FileKit/tree/develop) branch.\n\n## Installation\n\n### Compatibility\n\n- OS X 10.9+ / iOS 8.0+ / watchOS 2.0 / tvOS 9.0\n\n- Xcode 7.1+, Swift 2.1+\n\n### Install Using CocoaPods\n[CocoaPods](https://cocoapods.org/) is a centralized dependency manager for\nObjective-C and Swift. Go [here](https://guides.cocoapods.org/using/index.html)\nto learn more.\n\n1. Add the project to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html).\n\n    ```ruby\n    use_frameworks!\n\n    pod 'FileKit', '~\u003e 5.0.0'\n    ```\n\n2. Run `pod install` and open the `.xcworkspace` file to launch Xcode.\n\n3. Import the FileKit framework.\n\n    ```swift\n    import FileKit\n    ```\n\n### Install Using Carthage\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency\nmanager for Objective-C and Swift.\n\n1. Add the project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile).\n\n    ```\n    github \"nvzqz/FileKit\"\n    ```\n\n2. Run `carthage update` and follow [the additional steps](https://github.com/Carthage/Carthage#getting-started)\n   in order to add FileKit to your project.\n\n3. Import the FileKit framework.\n\n    ```swift\n    import FileKit\n    ```\n\n## Usage\n\n### Paths\n\nPaths are handled with the `Path` structure.\n\n```swift\nlet home = Path(\"~\")\nlet drive: Path = \"/Volumes/Macintosh HD\"\nlet file:  Path = \"~/Desktop/file\\(1)\"\n```\n\n#### Operations\n\n##### New Files\n\nA blank file can be written by calling `createFile()` on an `Path`.\n\n```swift\ntry Path(\".gitignore\").createFile()\n```\n\n##### New Directories\n\nA directory can be created by calling `createDirectory()` on an `Path`.\n\n```swift\ntry Path(\"~/Files\").createDirectory()\ntry Path(\"~/Books\").createDirectory(withIntermediateDirectories: false)\n```\n\nIntermediate directories are created by default.\n\n##### New Symlinks\n\nA symbolic link can be created by calling `createSymlinkToPath(_:)` on an `Path`.\n\n```swift\ntry Path(\"path/to/MyApp.app\").symlinkFile(to: \"~/Applications\")\nprint(Path(\"~/Applications/MyApp.app\").exists)  // true\n```\n\n##### Finding Paths\n\nYou can find all paths with the \".txt\" extension five folders deep into the\nDesktop with:\n\n```swift\nlet textFiles = Path.userDesktop.find(searchDepth: 5) { path in\n    path.pathExtension == \"txt\"\n}\n```\n\nA negative `searchDepth` will make it run until every path in `self` is checked\nagainst.\n\nYou can even map a function to paths found and get the non-nil results:\n\n```swift\nlet documents = Path.userDocuments.find(searchDepth: 1) { path in\n    String(path)\n}\n```\n\n##### Iterating Through Paths\n\nBecause `Path` conforms to `SequenceType`, it can be iterated through with a\n`for` loop.\n\n```swift\nfor download in Path.userDownloads {\n    print(\"Downloaded file: \\(download)\")\n}\n```\n\n##### Current Working Directory\n\nThe current working directory for the process can be changed with `Path.Current`.\n\nTo quickly change the current working directory to a path and back, there's the\n`changeDirectory(_:)` method:\n\n```swift\nPath.userDesktop.changeDirectory {\n    print(Path.current)  // \"/Users/nvzqz/Desktop\"\n}\n```\n\n##### Common Ancestor\n\nA common ancestor between two paths can be obtained:\n\n```swift\nprint(Path.root.commonAncestor(.userHome))       // \"/\"\nprint(\"~/Desktop\"  \u003c^\u003e \"~/Downloads\")            // \"~\"\nprint(.UserLibrary \u003c^\u003e .UserApplicationSupport)  // \"/Users/nvzqz/Library\"\n```\n\n##### `+` Operator\n\nAppends two paths and returns the result\n\n```swift\n// ~/Documents/My Essay.docx\nlet essay = Path.userDocuments + \"My Essay.docx\"\n```\n\nIt can also be used to concatenate a string and a path, making the string value\na `Path` beforehand.\n\n```swift\nlet numberedFile: Path = \"path/to/dir\" + String(10)  // \"path/to/dir/10\"\n```\n\n##### `+=` Operator\n\nAppends the right path to the left path. Also works with a `String`.\n\n```swift\nvar photos = Path.userPictures + \"My Photos\"  // ~/Pictures/My Photos\nphotos += \"../My Other Photos\"                // ~/Pictures/My Photos/../My Other Photos\n```\n\n##### `%` Operator\n\nReturns the standardized version of the path.\n\n```swift\nlet path: Path = \"~/Desktop\"\npath% == path.standardized  // true\n```\n\n##### `*` Operator\n\nReturns the resolved version of the path.\n\n```swift\nlet path: Path = \"~/Documents\"\npath* == path.resolved  // true\n```\n\n##### `^` Operator\n\nReturns the path's parent path.\n\n```swift\nlet path: Path = \"~/Movies\"\npath^ == \"~\"  // true\n```\n\n##### `-\u003e\u003e` Operator\n\nMoves the file at the left path to the right path.\n\n`Path` counterpart: **`moveFile(to:)`**\n\n`File` counterpart: **`move(to:)`**\n\n##### `-\u003e!` Operator\n\nForcibly moves the file at the left path to the right path by deleting anything\nat the left path before moving the file.\n\n##### `+\u003e\u003e` Operator\n\nCopies the file at the left path to the right path.\n\n`Path` counterpart: **`copyFile(to:)`**\n\n`File` counterpart: **`copy(to:)`**\n\n##### `+\u003e!` Operator\n\nForcibly copies the file at the left path to the right path by deleting anything\nat the left path before copying the file.\n\n##### `=\u003e\u003e` Operator\n\nCreates a symlink of the left path at the right path.\n\n`Path` counterpart: **`symlinkFile(to:)`**\n\n`File` counterpart: **`symlink(to:)`**\n\n##### `=\u003e!` Operator\n\nForcibly creates a symlink of the left path at the right path by deleting\nanything at the left path before creating the symlink.\n\n##### Subscripting\n\nSubscripting an `Path` will return all of its components up to and including\nthe index.\n\n```swift\nlet users = Path(\"/Users/me/Desktop\")[1]  // /Users\n```\n\n##### `standardize()`\n\nStandardizes the path.\n\nThe same as doing:\n```swift\nsomePath = somePath.standardized\n```\n\n##### `resolve()`\n\nResolves the path's symlinks.\n\nThe same as doing:\n```swift\nsomePath = somePath.resolved\n```\n\n### Files\n\nA file can be made using `File` with a `DataType` for its data type.\n\n```swift\nlet plistFile = File\u003cDictionary\u003e(path: Path.userDesktop + \"sample.plist\")\n```\n\nFiles can be compared by size.\n\n#### Operators\n\n##### `|\u003e` Operator\n\nWrites the data on the left to the file on the right.\n\n```swift\ndo {\n    try \"My name is Bob.\" |\u003e TextFile(path: Path.userDesktop + \"name.txt\")\n} catch {\n    print(\"I can't write to a desktop file?!\")\n}\n```\n\n#### TextFile\n\nThe `TextFile` class allows for reading and writing strings to a file.\n\nAlthough it is a subclass of `File\u003cString\u003e`, `TextFile` offers some functionality\nthat `File\u003cString\u003e` doesn't.\n\n##### `|\u003e\u003e` Operator\n\nAppends the string on the left to the `TextFile` on the right.\n\n```swift\nlet readme = TextFile(path: \"README.txt\")\ntry \"My Awesome Project\" |\u003e readme\ntry \"This is an awesome project.\" |\u003e\u003e readme\n```\n\n#### NSDictionaryFile\n\nA typealias to `File\u003cNSDictionary\u003e`.\n\n#### NSArrayFile\n\nA typealias to `File\u003cNSArray\u003e`\n\n#### NSDataFile\n\nA typealias to `File\u003cNSData\u003e`\n\n#### DataFile\n\nThe `DataFile` class allows for reading and writing `Data` to a file.\n\nAlthough it is a subclass of `File\u003cData\u003e`, `DataFile` offers some functionality\nthat `File\u003cData\u003e` doesn't. You could specify `Data.ReadingOptions` and `Data.WritingOptions`\n\n#### Encodable/Decodable\n\nYou can use any `Codable` object with `File`.\n\n```swift\nextension AnyCodableClass: JSONReadableWritable {} // if you want json encoding/decoding\n\nlet codableFile = File\u003cAnyCodableClass\u003e(path: path)\ntry codableFile.write(toEncode)\nlet decoded: AnyCodableClass = try codableFile.read()\n```\n\nAlternatively you can use utility methods\n\n```swift\ntry FileKit.write(toEncode, to: path)\nlet decoded: AnyCodableClass = try FileKit.read(from: path)\n```\n\n### File Permissions\n\nThe `FilePermissions` struct allows for seeing the permissions of the current\nprocess for a given file.\n\n```swift\nlet swift: Path = \"/usr/bin/swift\"\nprint(swift.filePermissions)  // FilePermissions[read, execute]\n```\n\n### Data Types\n\nAll types that conform to `DataType` can be used to satisfy the generic type for\n`File`.\n\n#### Readable Protocol\n\nA `Readable` type must implement the static method `read(from: Path)`.\n\nAll `Readable` types can be initialized with `init(contentsOfPath:)`.\n\n#### Writable Protocol\n\nA `Writable` type must implement `write(to: Path, atomically: Bool)`.\n\nWriting done by `write(to: Path)` is done atomically by default.\n\n##### WritableToFile\n\nTypes that have a `write(toFile:atomically:)` method that takes in a `String`\nfor the file path can conform to `Writable` by simply conforming to\n`WritableToFile`.\n\n##### WritableConvertible\n\nIf a type itself cannot be written to a file but can output a writable type,\nthen it can conform to `WritableConvertible` and become a `Writable` that way.\n\n### FileKitError\n\nThe type for all errors thrown by FileKit operations is `FileKitError`.\n\nErrors can be converted to `String` directly for any logging. If only the error\nmessage is needed, `FileKitError` has a `message` property that states why the\nerror occurred.\n\n```swift\n// FileKitError(Could not copy file from \"path/to/file\" to \"path/to/destination\")\nString(FileKitError.copyFileFail(from: \"path/to/file\", to: \"path/to/destination\"))\n```\n\n## License\n\nFileKit and its assets are released under the [MIT License](LICENSE.md). Assets\ncan be found in the [`assets`](https://github.com/nvzqz/FileKit/tree/assets)\nbranch.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvzqz%2FFileKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnvzqz%2FFileKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvzqz%2FFileKit/lists"}