Code Monkey home page Code Monkey logo

filekit's Introduction

FileKit is a Swift framework that allows for simple and expressive file management.

Development happens in the develop branch.

Installation

Compatibility

  • OS X 10.9+ / iOS 8.0+ / watchOS 2.0 / tvOS 9.0

  • Xcode 7.1+, Swift 2.1+

Install Using CocoaPods

CocoaPods is a centralized dependency manager for Objective-C and Swift. Go here to learn more.

  1. Add the project to your Podfile.

    use_frameworks!
    
    pod 'FileKit', '~> 5.0.0'
  2. Run pod install and open the .xcworkspace file to launch Xcode.

  3. Import the FileKit framework.

    import FileKit

Install Using Carthage

Carthage is a decentralized dependency manager for Objective-C and Swift.

  1. Add the project to your Cartfile.

    github "nvzqz/FileKit"
    
  2. Run carthage update and follow the additional steps in order to add FileKit to your project.

  3. Import the FileKit framework.

    import FileKit

Usage

Paths

Paths are handled with the Path structure.

let home = Path("~")
let drive: Path = "/Volumes/Macintosh HD"
let file:  Path = "~/Desktop/file\(1)"

Operations

New Files

A blank file can be written by calling createFile() on an Path.

try Path(".gitignore").createFile()
New Directories

A directory can be created by calling createDirectory() on an Path.

try Path("~/Files").createDirectory()
try Path("~/Books").createDirectory(withIntermediateDirectories: false)

Intermediate directories are created by default.

New Symlinks

A symbolic link can be created by calling createSymlinkToPath(_:) on an Path.

try Path("path/to/MyApp.app").symlinkFile(to: "~/Applications")
print(Path("~/Applications/MyApp.app").exists)  // true
Finding Paths

You can find all paths with the ".txt" extension five folders deep into the Desktop with:

let textFiles = Path.userDesktop.find(searchDepth: 5) { path in
    path.pathExtension == "txt"
}

A negative searchDepth will make it run until every path in self is checked against.

You can even map a function to paths found and get the non-nil results:

let documents = Path.userDocuments.find(searchDepth: 1) { path in
    String(path)
}
Iterating Through Paths

Because Path conforms to SequenceType, it can be iterated through with a for loop.

for download in Path.userDownloads {
    print("Downloaded file: \(download)")
}
Current Working Directory

The current working directory for the process can be changed with Path.Current.

To quickly change the current working directory to a path and back, there's the changeDirectory(_:) method:

Path.userDesktop.changeDirectory {
    print(Path.current)  // "/Users/nvzqz/Desktop"
}
Common Ancestor

A common ancestor between two paths can be obtained:

print(Path.root.commonAncestor(.userHome))       // "/"
print("~/Desktop"  <^> "~/Downloads")            // "~"
print(.UserLibrary <^> .UserApplicationSupport)  // "/Users/nvzqz/Library"
+ Operator

Appends two paths and returns the result

// ~/Documents/My Essay.docx
let essay = Path.userDocuments + "My Essay.docx"

It can also be used to concatenate a string and a path, making the string value a Path beforehand.

let numberedFile: Path = "path/to/dir" + String(10)  // "path/to/dir/10"
+= Operator

Appends the right path to the left path. Also works with a String.

var photos = Path.userPictures + "My Photos"  // ~/Pictures/My Photos
photos += "../My Other Photos"                // ~/Pictures/My Photos/../My Other Photos
% Operator

Returns the standardized version of the path.

let path: Path = "~/Desktop"
path% == path.standardized  // true
* Operator

Returns the resolved version of the path.

let path: Path = "~/Documents"
path* == path.resolved  // true
^ Operator

Returns the path's parent path.

let path: Path = "~/Movies"
path^ == "~"  // true
->> Operator

Moves the file at the left path to the right path.

Path counterpart: moveFile(to:)

File counterpart: move(to:)

->! Operator

Forcibly moves the file at the left path to the right path by deleting anything at the left path before moving the file.

+>> Operator

Copies the file at the left path to the right path.

Path counterpart: copyFile(to:)

File counterpart: copy(to:)

+>! Operator

Forcibly copies the file at the left path to the right path by deleting anything at the left path before copying the file.

=>> Operator

Creates a symlink of the left path at the right path.

Path counterpart: symlinkFile(to:)

File counterpart: symlink(to:)

=>! Operator

Forcibly creates a symlink of the left path at the right path by deleting anything at the left path before creating the symlink.

Subscripting

Subscripting an Path will return all of its components up to and including the index.

let users = Path("/Users/me/Desktop")[1]  // /Users
standardize()

Standardizes the path.

The same as doing:

somePath = somePath.standardized
resolve()

Resolves the path's symlinks.

The same as doing:

somePath = somePath.resolved

Files

A file can be made using File with a DataType for its data type.

let plistFile = File<Dictionary>(path: Path.userDesktop + "sample.plist")

Files can be compared by size.

Operators

|> Operator

Writes the data on the left to the file on the right.

do {
    try "My name is Bob." |> TextFile(path: Path.userDesktop + "name.txt")
} catch {
    print("I can't write to a desktop file?!")
}

TextFile

The TextFile class allows for reading and writing strings to a file.

Although it is a subclass of File<String>, TextFile offers some functionality that File<String> doesn't.

|>> Operator

Appends the string on the left to the TextFile on the right.

let readme = TextFile(path: "README.txt")
try "My Awesome Project" |> readme
try "This is an awesome project." |>> readme

NSDictionaryFile

A typealias to File<NSDictionary>.

NSArrayFile

A typealias to File<NSArray>

NSDataFile

A typealias to File<NSData>

DataFile

The DataFile class allows for reading and writing Data to a file.

Although it is a subclass of File<Data>, DataFile offers some functionality that File<Data> doesn't. You could specify Data.ReadingOptions and Data.WritingOptions

Encodable/Decodable

You can use any Codable object with File.

extension AnyCodableClass: JSONReadableWritable {} // if you want json encoding/decoding

let codableFile = File<AnyCodableClass>(path: path)
try codableFile.write(toEncode)
let decoded: AnyCodableClass = try codableFile.read()

Alternatively you can use utility methods

try FileKit.write(toEncode, to: path)
let decoded: AnyCodableClass = try FileKit.read(from: path)

File Permissions

The FilePermissions struct allows for seeing the permissions of the current process for a given file.

let swift: Path = "/usr/bin/swift"
print(swift.filePermissions)  // FilePermissions[read, execute]

Data Types

All types that conform to DataType can be used to satisfy the generic type for File.

Readable Protocol

A Readable type must implement the static method read(from: Path).

All Readable types can be initialized with init(contentsOfPath:).

Writable Protocol

A Writable type must implement write(to: Path, atomically: Bool).

Writing done by write(to: Path) is done atomically by default.

WritableToFile

Types that have a write(toFile:atomically:) method that takes in a String for the file path can conform to Writable by simply conforming to WritableToFile.

WritableConvertible

If a type itself cannot be written to a file but can output a writable type, then it can conform to WritableConvertible and become a Writable that way.

FileKitError

The type for all errors thrown by FileKit operations is FileKitError.

Errors can be converted to String directly for any logging. If only the error message is needed, FileKitError has a message property that states why the error occurred.

// FileKitError(Could not copy file from "path/to/file" to "path/to/destination")
String(FileKitError.copyFileFail(from: "path/to/file", to: "path/to/destination"))

License

FileKit and its assets are released under the MIT License. Assets can be found in the assets branch.

filekit's People

Contributors

alesete avatar dmazzoni avatar e-marchand avatar igormuzyka avatar jakeheis avatar jeehut avatar nvzqz avatar phimage avatar prayagverma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

filekit's Issues

NSFileHandle-based implementation and exceptions

I noticed that FileKit is based on NSFileHandle. NSFileHandle has an API that is based on (Objective-C) exceptions. The FileKit codebase currently does not catch those. IMO, this is required to make it possible to safely use FileKit (without arbitrary application terminations).

Support for hard links

Hi, I just ran into a case where I had to user a hard link instead of a symlink and had to fall back to NSFileManager to accomplish it. The API is almost identical to the symlink function:

createSymbolicLinkAtURL(_:withDestinationURL:)
createSymbolicLinkAtPath(_:withDestinationPath:)
linkItemAtURL(_:toURL:)
linkItemAtPath(_:toPath:)

Docs: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html#//apple_ref/doc/uid/20000305-SW30

Thanks! If I have some time I'll add this and submit a PR, but I wanted to at least raise the flag so the issue is logged.

Clean up API and add Swift 3 support

Future API should be written to be compatible with Swift 3.

Because Swift 2 support is being dropped, this is a breaking change that will result in a major version change for FileKit to 4.0.0.

Also, a lot of documentation is also either ambiguous or just weirdly worded.

Cleaning up the API entails following the Swift API Style Guidelines.

Note: Adding Swift 3 support consists of keeping this up to date with Swift 3 until a final release is made. Then there'll be no breaking changes, allowing for version 4.

  • Swift 3 compatibility #27
  • Cleaned up API

Typo in ReadMe?

+>! Operator

Forcibly copies the file at the left path to the right path by deleting anything at the left path before copying the file.

Should that be "Forcibly copies the file at the left path to the right path by deleting anything at the RIGHT path before copying the file." ? If not, wouldn't it be a move instead of a copy?

Path.children always returns 0 Results

Code Example

print(Path.userDesktop.children().count) // 0
print(Path("my path with children").children().count) // 0

Now, both of the paths that I tested with do have children but the .children() method seems to always return 0.

I was using version 5.0.0 with Swift 4 on a Mac OS app.

Cannot call value of non-function type 'FileType?'

Hi,
I'm getting a compiler error when building my macOS app using FileKit integrated with Cocoapods.

The app is for macOS 10.13. I'm using Xcode 9.0.1, Cocoapods and FileKit 4.0.1 (5.0.0 was not available over Cocoapods)

If I want to compile the I getting this error:

Cannot call value of non-function type 'FileType?' in

extension File: CustomStringConvertible {

    // MARK: - CustomStringConvertible

    /// A textual representation of `self`.
    public var description: String {
        return String(describing: type(of: self)) + "('" + path.description + "')"
    }

}

How to read and write line by line?

Why is it that there are no file read and write routines to read individual lines from a file, or write individual lines to a file, without having to open and close the file around each line (such as your |>> operator)?

I really love the Swift language, except that I can't read or write a text file in a normal manner. Reading the whole file at once is great... unless your file is several Megabytes, or several Terabytes long. I really just want to read a file, line by line, in a way that won't eat up all of memory.

I'm just frustrated, saw your library, and thought that it might be the solution I was looking for. O.o

Build Failing on Swift 3.1

PR #44 fixes the build error, but these changes have not been released yet. When will you release these as a minor version update?

Support Linux?

Hi, will FileKit support Linux as well? Currently I'm not able to build 3.0.0 tag due issue with Image+File.swift where is WatchKit imported, which is something that doesn't exist on Linux version of Swift.
Thanks.

v4.0.0 Release Notes

I was just wondering what the release notes for v4.0.0 are. On your releases page there are no release notes. I'd like to know what the changes are so I can upgrade accordingly.

Thanks!

Static let 'NowEventId' is internal and cannot be referenced from a default argument value

Hi,
I'm getting a compiler error when building my macOS app using FileKit integrated with Cocoapods.

The app is for macOS 10.13. I'm using Xcode 9.0.1, Cocoapods and FileKit 4.0.1 (5.0.0 was not available over Cocoapods)

If I want to compile the I getting this error:

Static let 'NowEventId' is internal and cannot be referenced from a default argument value

public init(paths: [Path],
                sinceWhen: FSEventStreamEventId = FileSystemEvent.NowEventId,
                flags: FileSystemEventStreamCreateFlags = [.UseCFTypes, .FileEvents],
                latency: CFTimeInterval = 0,
                queue: DispatchQueue? = nil,
                callback: @escaping (FileSystemEvent) -> Void
        ) {
        self.lastEventId = sinceWhen
        self.paths       = paths
        self.flags       = flags
        self.latency     = latency
        self.queue       = queue
        self._callback   = callback
    }

CocoaPods extremely out-of-date (5.2 when it should be 6.0)

I was able to find this issue #73 but I do not understand why it was closed without any resolution. Does no-one maintaining this project have access to update the Podspec in the public CocoaPods repo? I am happy to help in anyway I can to make this happen. Thanks!

testWatch() Fails on First Run

When testing FileKit, testWatch() will sometimes fail on the first attempt. I'm not familiar with GCD, so I don't necessarily know why this occurs.

del

del, sorry, found everything

CocoaPods version not updated

Your podspec/releases show 5.1.0, but cocoapods only has up to 5.0.0. Please run pod trunk push to update cocoapods with your latest podspec. Thanks!

Debugger support?

I've used FileKit for a while now, but a problem has plagued me often.
I'm never able to po anything FileKit related.

Any ideas why this is the case?

for example :
(lldb) po name
expression produced error: error: /var/folders/cs/51wtzgp51v157z25_b0fjqn80000gn/T/expr10-5d206b..swift:1:85: error: 'Path' is not a member type of 'FileKit'
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Swift.Array<FileKit.Path>>(bitPattern: 0x1037ff9e0)!.pointee)
~~~~~~~ ^

File System Watching Documentation

I read the release notes for v3.0.0, and "File system watching" caught my eye. I need to do file system watching in my application so that I can update a CollectionView as the contents of a directory change.

I don't see where usage of this feature is documented. Can you point me to where it is, or if there isn't any documentation, can you please provide some? I would love to take advantage of this feature.

Thanks!

Cannot convert value of type '[FileAttributeKey : Any]' to expected argument type '[String : Any]?'

Xcode9
after pod install
Swift Compiler Error Group:
/Users/matthewxu/project/LiLiTools/Pods/FileKit/Sources/FileProtection.swift:126:82: Cannot convert value of type '[FileAttributeKey : Any]' to expected argument type '[String : Any]?'
on manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) {
in the following codes

public func createFile(_ fileProtection: FileProtection) throws {
       let manager = FileManager()
       let attributes: [FileAttributeKey : Any] = [.protectionKey: fileProtection] // todo test

       if !manager.createFile(atPath: _safeRawValue, contents: nil, attributes: attributes) { 
           throw FileKitError.createFileFail(path: self)
       }
   }

Any one meet this issue and how to solve it

Swift 4.1 Compatibility

I am getting a single error on the latest release of FileKit (5.2.0), the error is:
Value of type 'UIImage' has no member 'pngData'

How to rename?

Although FileKit is a really great library, I have a small problem with it.
Situation: I want to copy a file from one location to another location with a different name. With the copyToPath method I get the file with the original name from path1 to path2. But: How do I rename the file there? Changing the name does not succeed, as name is read-only. So, I'm stuck a bit...
Perhaps you might give me hint for that - thanks a lot in advance!

  • Hardy

warning: 'ExpressibleByStringInterpolation' is deprecated

Hi,
When I build your component with carthage I have these warnings:

../Sources/Carthage/Checkouts/FileKit/Sources/Path.swift:1066:17: warning: 'ExpressibleByStringInterpolation' is deprecated: it will be replaced or redesigned in Swift 4.0.  Instead of conforming to 'ExpressibleByStringInterpolation', consider adding an 'init(_:String)'
../Sources/Carthage/Checkouts/FileKit/Sources/TextFile.swift:231:21: warning: conditional downcast from 'NSString?' to 'String' is a bridging conversion; did you mean to use 'as'?

Sorted Path's children

Hi,
how can I obtain the children of a Path sorted by descendant modified date, for example?

Cannot create directory/file with name has slash character.

let shared = Path.userDocuments
let x = shared + "h/ai"
try? x.createDirectory(withIntermediateDirectories: true)
let sample = TextFile(path: shared/"filekit_sample.txt")
try? sample.write("Hello there!")
try? sample.read()

This code always create two directory h and sub directory ai.

Support Decodable/Encodable (Swift 4)

In the past, I try to make some utility functions to work with NSCoding (branch feature-nscoding), write and read JSON

In swift 4 Decodable/Encodable (and Codable) allow to have a better interface to serialize objects

We can

  • write to file an Encodable object
  • write to file an array of Encodable objects
  • read from file an Decodable object
  • read from file an array of Decodable objects

That could be done only after merging #49

BUILD FAILED - Xcode 8.1 - Carthage

A shell task (/usr/bin/xcrun xcodebuild -project /Users/NEO/Workspace/Swift3/hsound/HSound/Carthage/Checkouts/FileKit/FileKit.xcodeproj -scheme FileKit-iOS -configuration Release -sdk iphoneos ONLY_ACTIVE_ARCH=NO BITCODE_GENERATION_MODE=bitcode CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES clean build) failed with exit code 65:
** BUILD FAILED **

The following build commands failed:
CompileSwift normal arm64
CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
(2 failures)

iOS should have UserDocuments as well

Can you allow Path.UsersDocuments for iOS in addition to OSX?
And can you make Path.pathInUserDomain, Path.pathsInDomains public? This way I can extend Path with more iOS paths such as UsersDocuments

Codable doesn't conform to ReadableWritable

I'm not sure if this is an oversight, but there's no default conformance for Codable to ReadableWriteable.

This conformance would allow for File<DataType: ReadableWritable> to work with any Codable and appears to be the intent as listed in the readme.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.