Path
MetadataErr
An error when reading a path's file metadata from disk.
Path
Represents a path to a file or directory on the filesystem.
DirEntry
Record which represents a directory
This is the same as
Dir.DirEntry
.
ReadErr
Tag union of possible errors when reading a file or directory.
This is the same as
File.ReadErr
.
WriteErr
Tag union of possible errors when writing a file or directory.
This is the same as
File.WriteErr
.
DirErr
NotFound - This error is raised when the specified directory does not exist, typically during attempts to access or manipulate it.
PermissionDenied - Occurs when the user lacks the necessary permissions to perform an action on a directory, such as reading, writing, or executing.
AlreadyExists - This error is thrown when trying to create a directory that already exists.
NotADirectory - Raised when an operation that requires a directory (e.g., listing contents) is attempted on a file instead.
Other - A catch-all for any other types of errors not explicitly listed above.
This is the same as
Dir.Err
.
write : val, Path, fmt -> Task {} [FileWriteErr Path WriteErr] where val implements Encoding, fmt implements EncoderFormatting
Write data to a file.
First encode a val
using a given fmt
which implements the ability Encode.EncoderFormatting.
For example, suppose you have a Json.toCompactUtf8
which implements
Encode.EncoderFormatting.
You can use this to write JSON
data to a file like this:
# Writes `{"some":"json stuff"}` to the file `output.json`: Path.write { some: "json stuff" } (Path.fromStr "output.json") Json.toCompactUtf8
This opens the file first and closes it after writing to it.
If writing to the file fails, for example because of a file permissions issue, the task fails with WriteErr
.
To write unformatted bytes to a file, you can use
Path.writeBytes
instead.
writeBytes : List U8, Path -> Task {} [FileWriteErr Path WriteErr]
Writes bytes to a file.
# Writes the bytes 1, 2, 3 to the file `myfile.dat`. Path.writeBytes [1, 2, 3] (Path.fromStr "myfile.dat")
This opens the file first and closes it after writing to it.
To format data before writing it to a file, you can use
Path.write
instead.
writeUtf8 : Str, Path -> Task {} [FileWriteErr Path WriteErr]
Writes a Str
to a file, encoded as UTF-8.
# Writes "Hello!" encoded as UTF-8 to the file `myfile.txt`. Path.writeUtf8 "Hello!" (Path.fromStr "myfile.txt")
This opens the file first and closes it after writing to it.
To write unformatted bytes to a file, you can use
Path.writeBytes
instead.
fromStr : Str -> Path
Note that the path may not be valid depending on the filesystem where it is used.
For example, paths containing :
are valid on ext4 and NTFS filesystems, but not
on FAT ones. So if you have multiple disks on the same machine, but they have
different filesystems, then this path could be valid on one but invalid on another!
It's safest to assume paths are invalid (even syntactically) until given to an operation which uses them to open a file. If that operation succeeds, then the path was valid (at the time). Otherwise, error handling can happen for that operation rather than validating up front for a false sense of security (given symlinks, parts of a path being renamed, etc.).
fromBytes : List U8 -> Path
Not all filesystems use Unicode paths. This function can be used to create a path which
is not valid Unicode (like a Str
is), but which is valid for a particular filesystem.
Note that if the list contains any 0
bytes, sending this path to any file operations
(e.g. Path.readBytes
or WriteStream.openPath
) will fail.
display : Path -> Str
Unfortunately, operating system paths do not include information about which charset
they were originally encoded with. It's most common (but not guaranteed) that they will
have been encoded with the same charset as the operating system's curent locale (which
typically does not change after it is set during installation of the OS), so
this should convert a Path
to a valid string as long as the path was created
with the given Charset
. (Use Env.charset
to get the current system charset.)
For a conversion to Str
that is lossy but does not return a Result
, see
display
.
toInner : Path -> Str Str, Bytes (List U8)
Assumes a path is encoded as UTF-8,
and converts it to a string using Str.display
.
This conversion is lossy because the path may contain invalid UTF-8 bytes. If that happens,
any invalid bytes will be replaced with the Unicode replacement character
instead of returning an error. As such, it's rarely a good idea to use the Str
returned
by this function for any purpose other than displaying it to a user.
When you don't know for sure what a path's encoding is, UTF-8 is a popular guess because it's the default on UNIX and also is the encoding used in Roc strings. This platform also automatically runs applications under the UTF-8 code page on Windows.
Converting paths to strings can be an unreliable operation, because operating systems
don't record the paths' encodings. This means it's possible for the path to have been
encoded with a different character set than UTF-8 even if UTF-8 is the system default,
which means when display
converts them to a string, the string may include gibberish.
Here is an example.
If you happen to know the Charset
that was used to encode the path, you can use
toStrUsingCharset
instead of display
.
isDir : Path -> Task Bool [PathErr MetadataErr]
Returns true if the path exists on disk and is pointing at a directory.
Returns Task.ok false
if the path exists and it is not a directory. If the path does not exist,
this function will return Task.err PathErr PathDoesNotExist
.
This uses rust's std::path::is_dir.
File.isDir
does the same thing, except it takes aStr
instead of aPath
.
isFile : Path -> Task Bool [PathErr MetadataErr]
Returns true if the path exists on disk and is pointing at a regular file.
Returns Task.ok false
if the path exists and it is not a file. If the path does not exist,
this function will return Task.err PathErr PathDoesNotExist
.
This uses rust's std::path::is_file.
File.isFile
does the same thing, except it takes aStr
instead of aPath
.
isSymLink : Path -> Task Bool [PathErr MetadataErr]
Returns true if the path exists on disk and is pointing at a symbolic link.
Returns Task.ok false
if the path exists and it is not a symbolic link. If the path does not exist,
this function will return Task.err PathErr PathDoesNotExist
.
This uses rust's std::path::is_symlink.
File.isSymLink
does the same thing, except it takes aStr
instead of aPath
.
type : Path -> Task [ IsFile, IsDir, IsSymLink ] [PathErr MetadataErr]
Return the type of the path if the path exists on disk.
File.type
does the same thing, except it takes aStr
instead of aPath
.
withExtension : Path, Str -> Path
If the last component of this path has no .
, appends .
followed by the given string.
Otherwise, replaces everything after the last .
with the given string.
# Each of these gives "foo/bar/baz.txt" Path.fromStr "foo/bar/baz" |> Path.withExtension "txt" Path.fromStr "foo/bar/baz." |> Path.withExtension "txt" Path.fromStr "foo/bar/baz.xz" |> Path.withExtension "txt"
delete : Path -> Task {} [FileWriteErr Path WriteErr]
Deletes a file from the filesystem.
Performs a DeleteFile
on Windows and unlink
on
UNIX systems. On Windows, this will fail when attempting to delete a readonly
file; the file's readonly permission must be disabled before it can be
successfully deleted.
# Deletes the file named Path.delete (Path.fromStr "myfile.dat") [1, 2, 3]
This does not securely erase the file's contents from disk; instead, the operating system marks the space it was occupying as safe to write over in the future. Also, the operating system may not immediately mark the space as free; for example, on Windows it will wait until the last file handle to it is closed, and on UNIX, it will not remove it until the last hard link to it has been deleted.
File.delete
does the same thing, except it takes aStr
instead of aPath
.
readUtf8 : Path -> Task Str [ FileReadErr Path ReadErr, FileReadUtf8Err Path ]
Reads a Str
from a file containing UTF-8-encoded text.
# Reads UTF-8 encoded text into a Str from the file "myfile.txt" Path.readUtf8 (Path.fromStr "myfile.txt")
This opens the file first and closes it after writing to it.
The task will fail with FileReadUtf8Err
if the given file contains invalid UTF-8.
To read unformatted bytes from a file, you can use
Path.readBytes
instead.
File.readUtf8
does the same thing, except it takes aStr
instead of aPath
.
readBytes : Path -> Task (List U8) [FileReadErr Path ReadErr]
Reads all the bytes in a file.
# Read all the bytes in `myfile.txt`. Path.readBytes (Path.fromStr "myfile.txt")
This opens the file first and closes it after reading its contents.
To read and decode data from a file, you can use
Path.read
instead.
File.readBytes
does the same thing, except it takes aStr
instead of aPath
.
listDir : Path -> Task (List Path) [DirErr DirErr]
Lists the files and directories inside the directory.
Dir.list
does the same thing, except it takes aStr
instead of aPath
.
deleteEmpty : Path -> Task {} [DirErr DirErr]
Deletes a directory if it's empty
This may fail if:
- the path doesn't exist
- the path is not a directory
- the directory is not empty
- the user lacks permission to remove the directory.
Dir.deleteEmpty
does the same thing, except it takes aStr
instead of aPath
.
deleteAll : Path -> Task {} [DirErr DirErr]
Recursively deletes a directory as well as all files and directories inside it.
This may fail if:
- the path doesn't exist
- the path is not a directory
- the directory is not empty
- the user lacks permission to remove the directory.
Dir.deleteAll
does the same thing, except it takes aStr
instead of aPath
.
createDir : Path -> Task {} [DirErr DirErr]
Creates a directory
This may fail if:
- a parent directory does not exist
- the user lacks permission to create a directory there
- the path already exists.
Dir.create
does the same thing, except it takes aStr
instead of aPath
.
createAll : Path -> Task {} [DirErr DirErr]
Creates a directory recursively adding any missing parent directories.
This may fail if:
- the user lacks permission to create a directory there
- the path already exists
Dir.createAll
does the same thing, except it takes aStr
instead of aPath
.