Skip to content

Repository files navigation

Run shell commands | Parse command line arguments | Handle files and directories


Build StatusPlatforms

FileSmith

A strongly typed Swift library for working with local files and directories.

It differentiates between file paths and directory paths, and between paths and actual files and directories, because the programmer knows which are which and when the compiler knows it too it can be much more helpful.

See also:

Features

  • Separate types for file paths, directory paths, reading files, writing files, and directories.
  • Use Swifts native error handling.
  • List the contents of directories (recursively if needed).
  • Filter with glob wildcard patterns.
  • Sandbox mode prohibits changes outside of the current working directory.
  • Write text to files the same way you use Swift's print function.

Terms

Path:
The location of an item which may or may not exist in the local file system. It is either a DirectoryPath, FilePath or AnyPath.

File:
An existing regular file or something file-like which you can read from and/or write to, like streams, pipes or sockets. Or symbolic links to any of these.

Directory:
An existing directory or a symbolic link to a directory. Basically anything you can cd into in the terminal.

Item:
(for lack of a better term)
A file or a directory. Anything with a path in the file system.

Safety first

When Directory.sandbox == true (and it is by default) you can only change files or create new files and directories if they are under the current working directory. Trying to make changes elsewhere throws an error.

Usage

Change current working directory

DirectoryPath.current ="/tmp"Directory.current =Directory.createTempDirectory()
// common functionality
letdirpath=DirectoryPath("dir/dir1")varfilepath:FilePath="file.txt"
filepath =FilePath(base:"dir", relative:"file.txt")
filepath =FilePath("dir/file.txt")
filepath.relativeString
filepath.base?.string
filepath.absoluteString
filepath.string // relativeString ?? absoluteString
filepath.name
filepath.nameWithoutExtension
filepath.extension
// DirectoryPath only
dirpath.append(file:"file.txt") // FilePath("dir/dir1/file.txt")
dirpath.append(directory:"dir2") // DirectoryPath("dir/dir1/dir2")
dirpath.isAParentOf(filepath)

Create

vardir1=try dirpath.create(ifExists:.replace)vardir2=tryDirectory(create:"dir/dir2", ifExists:.throwError)vardir3=try dir2.create(directory:"dir3", ifExists:.open) // dir/dir2/dir3
varfile1_edit=try filepath.create(ifExists:.open)letfile2_edit=tryWritableFile(create:"file2.txt", ifExists:.open)letfile3_edit=try dir1.create(file:"file3.txt", ifExists:.open) // dir/dir1/file3

Open

dir1 =try dirpath.open()
dir2 =tryDirectory(open:"dir/dir2")
dir3 =try dir2.open(directory:"dir3")letfile1=try filepath.open()letfile2=tryReadableFile(open:"file2.txt")letfile3=try dir1.open(file:"file3.txt")

Read/Write

file1_edit.encoding =.utf16 // .utf8 by default
file1_edit.write("some text...")
file1_edit.print("Just like Swift's own 'print' function.")
file1_edit.print(2,"words", separator:"-", terminator:"")
file2.write(to:&file1_edit)letcontents:String= file3.read()forlinein file3.lines(){ // a lazy sequence
// ...
}whilelet text = file3.readSome(){
// read pipes etc. piece by piece, instead of waiting until they are closed.
}

Search/Filter

Directory.current.files(recursive:true) // [file2.txt, dir/file1.txt, dir/dir1/file3.txt]
dir1.files("*3.*", recursive:true) // [file3.txt]
Directory.current.directories(recursive:true) // [dir, dir/dir1, dir/dir2, dir/dir2/dir3]

Symbolic links

letdir1_link=tryDirectory(createSymbolicLink:"dir1_link", to: dir1, ifExists:.open)letdir2_link=try dir1.create(symbolicLink:"dir2_link", to: dir2, ifExists:.open)letfile1_link=tryReadableFile(createSymbolicLink:"file1_link", to: file1, ifExists:.open)letfile2_link=try dir2.create(symbolicLink:"file2_link", to: file2, ifExists:.open)asReadableFile

Misc

// the path of a file or directory
file1.path // FilePath
dir1.path // DirectoryPath
// remove files and directories
try file1_edit.delete()try dir1.delete()

Types

When opening files symbolic links are always followed, so the type of a file is never .symbolicLink, but can be .brokenSymbolicLink for symbolic links whose targets do not exist.

FileType("file.txt")FileType(filepath)publicenumFileType:Equatable,Hashable{case regularFile
case directory
case characterSpecial
case blockSpecial
case socket
case brokenSymbolicLink
case namedPipe
case unknown
}

Installation

Add .package(url: "https://github.com/kareman/FileSmith", from: "0.3.0") to your Package.swift:

import PackageDescription
letpackage=Package(
name:"somename",
dependencies:[.package(url:"https://github.com/kareman/FileSmith", from:"0.3.0")])

and run swift build.

Add FileSmith to your Podfile.

pod"FileSmith",git: "https://github.com/kareman/FileSmith.git"

Then run pod install to install it.

License

Released under the MIT License (MIT), http://opensource.org/licenses/MIT

Kåre Morstøl, NotTooBad Software

About

A strongly typed Swift library for working with local files and directories.

Topics

Resources

Stars

27 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages