FileSystem
is a simple and concise protocol orientated framework for dealing with the file system on iOS, tvOS, watchOS and macOS.
For safety and consistency all of the Item
based APIs are implemented as functions that can throw an error. This is predominately driven by the fact the other processes outside of an app's control can modify the file system at any time, coupled with the fact that Swift 3 has no concept of properties that can throw an error.
The main Types in FileSystem
are listed below with protocols being emphasised:
- Path
- PathRepresentable
- Parent
- Subitem
- Copyable
- CopyableSubitem
- Moveable
- MoveableSubitem
- Renameable
- Removable
- Trashable
- Linkable
- SymbolicLinkable
- Aliasable
- FileHandleConvertible
- FileWrapperConvertible
- Item
- File
- RegularFile
- SymbolicLink
- AliasFile
- Directory
- Volume
Path
is used to represent a location on disk, meaning that you no longer have to keep switching between String
and URL
.
Path
is RawRepresentable
by a String
, so can it be initialised using the default initialiser (which will return nil if the rawValue
is invalid):
let path = Path(rawValue: "/")
As this is so common you can omit the rawValue
parameter label:
let path = Path("/")
Path adopts ExpressibleByStringLiteral
, meaning that when the type can be inferred by the compiler you can omit the initialiser altogether:
let path: Path = "/"
As mentioned before the current APIs use a mixture of String
and URL
representations, so to make things easier Path
can also be initialised with a file URL:
let path = Path(url)
Path
has various APIs for accessing its components:
public var components: [String]
public var lastComponent: String
public var componentsToDisplay: [String]?
In addition to creating new paths based on its existing components:
public func appendingComponent(_ component: String) -> Path
public func deletingLastComponent() -> Path
public func replacingLastComponent(with component: String) -> Path
There is an API to access the path’s extension:
public var `extension`: String
There are APIs to resolve and standardise a Path
:
public var resolved: Path
public var standardized: Path
In addition to seeing if a Path
already exists:
public var exists: Bool
To access the Item
at a given path you can use the item property:
public var item: Item?
PathRepresentable
can be adopted by anything that can be represented by a Path
.
var path: Path { get }
init?(path: Path)
The initializer should return nil if the PathRepresentable
does not exist or if it is not of the correct type.
Item
is the base protocol
for all file system items that can be represented by Path
. Item
adopts PathRepresentable
, CustomStringConvertible
and CustomDebugStringConvertible
.
Item
adds an additonal initailzer that doesn't the check to see if the Item
exists at the given Path
, which is used internally by the FileSystem
framework for efficiency (e.g. when a valid path representation has been returned by a system API):
init(_ path: Path)
It also requires that the path property can be set:
var path: Path { get set }
Item
has the following APIs:
public func exists() throws -> Bool
public func localizedName() throws -> String
public func isReadable() throws -> Bool
public func isWritable() throws -> Bool
public func isExecutable() throws -> Bool
public func isHidden() throws -> Bool
public func isPackage() throws -> Bool
public func isApplication() throws -> Bool
public func isAliasFile() throws -> Bool
public func isSymbolicLink() throws -> Bool
public func creationDate() throws -> Date
public func contentAccessDate() throws -> Date
public func contentModificationDate() throws -> Date
public func attributeModificationDate() throws -> Date
public func attributes() throws -> [FileAttributeKey: Any]
public func setAttributes(_ attributes: [FileAttributeKey: Any]) throws
Parent
protocol
for an Item
that can be a parent of another Item
.
The Parent
protocol
provides APIs for accessing its subitems:
func subitems() throws -> [Subitem]
func isEmpty() throws -> Bool
func contains(_ subitem: Subitem) throws -> Bool
Subitem
protocol
for an Item
that can be a subitem of another Item
.
The Subitem
protocol
provides APIs to access its root volume and parent directory:
func rootVolume() throws -> Volume
func parentDirectory() throws -> Directory?
Copyable
protocol
for an Item
that can be a copied.
func copy(to path: Path) throws -> Self
CopyableSubitem
protocol
for an Item
that adopts Copyable
and Subitem
.
func copy(into parent: Parent) throws -> Self
Moveable
protocol
for an Item
that can be moved to another Path
.
mutating func move(to path: Path) throws
MoveableSubitem
protocol
for an Item
that adopts Moveable
and Subitem
.
mutating func move(into parent: Parent) throws
Renameable
protocol
for an Item
that can be renamed.
mutating func rename(to name: String) throws
Renameable
protocol
for an Item
that can be removed, note that the item is removed instantly.
func remove() throws
Trashable
protocol
for an Item
that can be trashed.
On macOS the protocol
has has the following APIs:
mutating func trash() throws
Linkable
protocol
for an Item
that can be hard linked to a Path
.
func link(to path: Path) throws -> Linkable
SymbolicLinkable
protocol
for an Item
that can be symbolic linked to a Path
.
func symbolicLink(to path: Path) throws -> SymbolicLink
Aliasable
protocol
for an Item
that can be aliased.
FileHandleConvertible
protocol
for an Item
that can be converted into a FileHandle
for either reading, writing or updating (both reading and writing).
func fileHandleForReading() throws -> FileHandle
func fileHandleForWriting() throws -> FileHandle
func fileHandleForUpdating() throws -> FileHandle
FileWrapperConvertible
protocol
for an Item
that can be converted into a FileWrapper
.
func fileWrapper() throws -> FileWrapper
File
is the base protocol
for a single file and adopts Item
, Subitem
, Copyable
, CopyableSubitem
, Moveable
, MoveableSubitem
, Renameable
, Removeable
, Trashable
, Linkable
, SymbolicLinkable
and Aliasable
.
File
has the following APIs:
public func isContentEqual(to file: Self) -> Bool
RegularFile
is a struct
that adopts File
, FileHandleConvertible
and FileWrapperConvertible
, and is used to represent a regular file i.e. not a symlink or alias.
RegularFile
has the following API:
public func size() throws -> Int
SymbolicLink
is a struct
that adopts File
and FileWrapperConvertible
, and is used to represent a symbolic link.
SymbolicLink
includes an API to retrieve its destination:
public func destination() throws -> SymbolicLinkable
AliasFile
is a struct
that adopts the File
protocol
and is used to represent an alias file.
AliasFile
includes an API to retrieve its destination:
public func destination() throws -> Aliasable
Directory
is a struct
that adopts Item
, Parent
, Subitem
, Copyable
, CopyableSubitem
, Moveable
, MoveableSubitem
, Renameable
, Removeable
, Trashable
, SymbolicLinkable
, Aliasable
and FileWrapperConvertible
.
Directory
has APIs to access system directories:
public static var temporary: Directory
public static var document: Directory
public static var library: Directory
public static var caches: Directory
public static var application: Directory
public static var applicationSupport: Directory
public static var desktop: Directory
public static var downloads: Directory
public static var movies: Directory
public static var music: Directory
public static var pictures: Directory
public static var applications: [Directory]
public static var libraries: [Directory]
Directory
has an API to access its relationship to another Item
:
public func relationship(to item: Item) throws -> FileManager.URLRelationship
In addition to an API for creating a Directory
at a Path
:
static public func create(at path: Path, withIntermediateDirectories: Bool = false, attributes: [String : Any]? = nil) throws -> Directory
There is also an API for returning container directories:
public static func container(forSecurityApplicationGroupIdentifier groupIdentifier: String) -> Directory?
Volume
is a struct
that adopts Item
, Parent
, Renameable
, Linkable
and SymbolicLinkable
.
Volume
provides an an API to access all of the mounted volumes:
public static var mounted: [Volume]
In addition to APIs to access information about the Volume
itself:
public func totalCapacity() throws -> Int
public func availableCapacity() throws -> Int
public func usedCapacity() throws -> Int
public func isEjectable() throws -> Bool
public func isRemovable() throws -> Bool
public func isInternal() throws -> Bool
public func isLocal() throws -> Bool
public func isReadOnly() throws -> Bool
On macOS you can also unmount the Volume
:
public func unmount(withOptions options: FileManager.UnmountOptions = [], completionHandler: @escaping (Error?) -> Void)