On this page:
filesystem.type
filesystem.file_  exists
filesystem.directory_  exists
filesystem.link_  exists
filesystem.files
filesystem.roots
filesystem.rename
filesystem.delete
filesystem.make_  directory
filesystem.make_  link
filesystem.make_  temporary
filesystem.Temporary
filesystem.Temporary.path
filesystem.Temporary.is_  directory
filesystem.copy
filesystem.size
filesystem.modify_  seconds
filesystem.permissions
filesystem.identity
filesystem.stat
filesystem.read_  bytes
filesystem.read_  string
filesystem.read_  bytes_  lines
filesystem.read_  lines
filesystem.write_  bytes
filesystem.write_  string
filesystem.simplify_  path
filesystem.normalize_  path
filesystem.resolve_  path
filesystem.expand_  user_  path
filesystem.current_  force_  delete_  permissions
8.16.0.1

14.3 Filesystem🔗ℹ

function

fun filesystem.type(path :: PathString,

                    ~must_exist: must_exist = #false)

  :: matching(#'file || #'directory || #'link || #'directory_link || #false)

Reports whether path refers to an existing file, directory, or soft link, returning a corresponding symbol or #false if path does not exist. If must_exist is true, then #false is never returned, and an exception is thrown, instead.

The result can be #'directory_link only on Windows, which distinguishes file and directory links.

Reports whether path refers to an existing file, directory, or soft link, respectively. The filesystem.link_exists result is not mutually exclusive with the other two: when path refers to a soft link, filesystem.file_exists and filesystem.directory_exists report whether the link reaches a file or directory.

function

fun filesystem.files(

  path :: PathString = Path.current_directory(),

  ~add_path: add_path = #false,

  ~recur: recur = #false,

  ~follow_links: follow_links = #false,

  ~keep: keep :: Path -> Any = fun (x): #true,

  ~skip: skip :: Path -> Any = fun (x): #false

) :: List.of(Path)

Returns a list of paths within the directory referenced by path. Each path in the result list is relative to path, unless add_path is true, in which case Path.add is used with path and each result path in the list.

If recur is #false, then the result includes only files, directories, and links immediately within path. If recur is true, then each directory within path is followed by its own recursive content in the result list. If follow_links true, the a recursive traversal continues into a link that refers to a directory, otherwise the link is not traversed for the result list; link cycles can cause filesystem.files to never return.

The keep and skip functions are applied to every path encountered during a traversal, and a path is omitted from the list when keep returns #false or skip returns a true value for the path. When recur is true, skipping a directory (or link that refers to a directory) means that it is not traversed, so the directory’s content is also skipped. If keep returns #false for a path, then skip is not applied to the path.

Returns a list of all roots on the current filesystem. For a filesystem that uses Unix path conventions, the result is always [Path("/")], but the result list can contain multiple drive paths on Windows.

function

fun filesystem.rename(path :: PathString,

                      to_path :: PathString,

                      ~exists_ok: exists_ok = #false)

  :: Void

Renames the file or directory path to to_path. If exists_ok is true, then renaming can replace an existing file.

When exists_ok is #false, a check is needed before the move operation internally, and that combination is not atomic on Unix and Mac OS. If to_path exists and is replaced (when exists_ok is true), then the replacement is atomic on Unix and Mac OS, but not necessarily atomic on Windows.

function

fun filesystem.delete(

  path :: PathString,

  ~as: mode :: matching(#'any || #'file || #'directory) = #'any,

  ~recur: recur = #false,

  ~must_exist: must_exist = #true

) :: Void

Deletes the file, directory, or link referenced by path. If mode is #'file, then path must refer to a file or link, and if mode is #'directory, then path must refer to a directory.

If recur is true and if path refers to a directory, then each file and directory within path is recursively deleted before attempting to delete path itself. When a link that refers to a directory is deleted, then the directory content is not deleted through the link, even when recur is true.

If must_exist is #true and path does not refer to a file, directory, or link, then an exception is thrown.

When mode is #'any or must_exist is #false, the check for path’s type/existence is not atomic combined with the deletion of path, so an exception can be thrown if a file, directory or link disappears or changes between the check and deletion.

On Windows, a file or link is deleted by first renaming it to a file in the temporary directory reported by system.path(#'temp_dir), and then deleting the file there. That two-step process can succeed in situations when a file might otherwise be locked by an asynchronous background process. If moving the file does not succeed, it is instead deleted in-place. See also filesystem.current_force_delete_permissions.

function

fun filesystem.make_directory(

  path :: PathString,

  ~parents: parents = #false,

  ~permissions: permissions :: Int.in(0, 65535) = 0o777

) :: Void

Creates a directory path. If parents is true, then any non-existent parent of path is created, first. If parents is #false and path exists already, then an exception is thrown.

The permissions argument specifies permissions used for a new created directory on Unix and Mac OS. The given permissions are adjusted based on the current process’s umask. The permissions argument is ignored on Windows.

function

fun filesystem.make_link(to_path :: PathString,

                         path :: PathString)

  :: Void

Creates path as a soft link whose content is the byte-string form of path. An exception is thrown if path exists already.

function

fun filesystem.make_temporary(

  ~in: dir :: PathString = system.path(#'temp_dir),

  ~as: mode :: (PathString || matching(#'file) || matching(#'directory))

         = #'file,

  ~make_name: make_name :: String -> Path.Relative

                = fun (s): Path("tmp" +& s),

  ~permissions: permissions :: maybe(Int.in(0, 65535))

                  = #false,

  ~replace_permissions: replace_permissions = #false

) :: filesystem.Temporary

 

class

class filesystem.Temporary(path :: Path,

                           is_directory :: Any.to_boolean):

  implements Closeable

Creates a temporary file or directory within dir and returns a filesystem.Temporary, which contains a path to the created file. If mode is a path or #'file, the result contains a file path, otherwise it contains a directory path. If mode is a path, the temporary file is created as a copy of mode.

A filesystem.Temporary object is Closeable, which means that it can be used with Closeable.let. The Closeable.close implementation for filesystem.Temporary deletes the temporary file or directory, recursively deleting content in the case of a temporary directory.

The name of the temporary file is based on the current time and the make_name function. The argument to make_name is a string containing only ASCII digits. The path returns by make_name is added to dir, and if a file, directory, or link with that name exists already, filesystem.make_temporary starts again to try a new file name.

The permissions and replace_permissions arguments apply to the newly created file. When mode as a path, the permissions argument as used as in filesystem.copy. Otherwise, the permissions arguments are used as in Port.Output.open_file or filesystem.make_directory.

fun process_big_data(src :: Path):

  Closeable.let tmp = filesystem.make_temporary()

  setup(src, tmp.path)

  work(tmp.path)

  finish(tmp.path) // produces result

  // `tmp.path` is deleted on return or on exception

function

fun filesystem.copy(

  src_path :: PathString,

  dest_path :: PathString,

  ~recur: recur = #false,

  ~exists_ok: exists_ok = #false,

  ~follow_links: follow_links = #true,

  ~permissions: permissions :: maybe(Int.in(0, 65535)) = #false,

  ~replace_permissions: replace_permissions = #true,

  ~keep_modify_seconds: keep_modify_seconds = #false

) :: Void

Copies the file or link src_path to dest_path, or recursively copies a directory when recur is true.

If exists_ok is false, an exception is thrown if dest_path exists already. When exists_ok is true, recur is true, and a directory is copied, then the content of src_path is effectively spliced with any existing directory tree dest_path.

When follow_links is #false, then a link is copied to a new link. Otherwise, the target of the link is copied to the new path.

The permissions argument is used for newly created files and directories. When it is #false, then a new file or directory uses the permissions of the copied files or directory, otherwise permissions is used for both copied files and new directories. On Windows, if permissions is supplied as non-#false, then after copying, dest_path is set to read-only or not depending on whether the 0o2 bit is present in permissions.

The replace_permissions argument is used only on Unix and Mac OS. When a dest_path is created, it is created with permissions or the permissions of src_path; however, the process’s umask may unset bits in the requested permissions. When dest_path already exists (and exists_ok is true), then the permissions of dest_path are initially left as-is. Finally, when replace_permissions is a true value, then the permissions of dest_path are set after the file content is copied (using again permissions or the permissions of src_path) without modification by the process’s umask.

On Windows, the modification time of src_path is transferred to dest_path. When keep_modify_seconds is true, then on Unix and Mac OS, too, the modification time of src_path is transferred to dest_path after copying.

Returns the size of the file referenced by path. An exception is thrown if path does not refer to an existing file.

function

fun filesystem.modify_seconds(

  path :: PathString,

  ~set_to: set_to :: maybe(Int) = #false,

  ~must_exist: must_exist = #true

) :: maybe(Int) || Void

Returns or changes (when set_to is not #false) the modification timestamp of path.

If path cannot be accessed or the modification timestamp cannot be changed, an exception is thrown only if must_exist is #false. Otherwise, #false is reported for an inaccessible timestamp and failure is silently ignored (and #void is still returned) when setting a timestamp fails.

function

fun filesystem.permissions(

  path :: PathString,

  ~bits: bits = #false,

  ~set_to: set_to :: maybe(Int.in(0, 65535)) = #false

) :: Int || Set.of(matching(#'read || #'write || #'execute)) || Void

Returns or changes (when set_to is not #false) the permissions of path.

When set_to is provided, the result is #void. Otherwise, the result is an integer when bits is true, or it is a list of distinct symbols when bits is false. A symbol-list result summarizes permissions for the current process’s user and group.

function

fun filesystem.identity(

  path :: PathString,

  ~follow_links: follow_links = #true

) :: PosInt

Returns an integer representing the identity of the file or directory referenced by path. This function can be used to check whether two paths correspond to the same filesystem object.

When path refers to a link, the result is the identity of the link when follow_links is #false, otherwise it is the identity of the link target.

function

fun filesystem.stat(path :: PathString,

                    ~follow_links: follow_links = #true)

  :: Map

Returns a symbol-keyed map containing information about path. The map includes information available from filesystem.type, filesystem.modify_seconds, filesystem.permissions, filesystem.identity, and other functions, but potentially in a more detailed form. This information is relatively low-level, and the result map uses Racket-style symbols as keys.

If path refers to a link, then the result map describes the target of the link unless follow_links is false.

function

fun filesystem.read_bytes(

  path :: PathString,

  ~mode: mode :: Port.Mode = #'binary

) :: Bytes

 

function

fun filesystem.read_string(

  path :: PathString,

  ~mode: mode :: Port.Mode = #'binary

) :: String

Returns the content of the file referenced by path, either in byte form or string form. The latter corresponds to a UTF-8 decoding of the file’s bytes.

function

fun filesystem.read_bytes_lines(

  path :: PathString,

  ~mode: mode :: Port.Input.ReadLineMode = #'any

) :: List.of(String)

 

function

fun filesystem.read_lines(

  path :: PathString,

  ~mode: mode :: Port.Input.ReadLineMode = #'any

) :: List.of(String)

Returns the content of the file referenced by path as a list of byte-string or string lines. The latter corresponds to a UTF-8 decoding of the file’s bytes. The mode argument is the same as for Port.Input.open_file.

function

fun filesystem.write_bytes(

  path :: PathString,

  bstr :: Bytes,

  ~exists: exists :: Port.Output.ExistsMode = #'error,

  ~mode: mode :: Port.Mode = #'binary

) :: Void

 

function

fun filesystem.write_string(

  path :: PathString,

  str :: String,

  ~exists: exists :: Port.Output.ExistsMode = #'error,

  ~mode: mode :: Port.Mode = #'binary

) :: Void

Replaces the content of path with bstr or the UTF-8 encoding of str. The mode and exists arguments are the same as for Port.Output.open_file.

The filesystem.simplify_path is similar to Path.simplify, but filesystem.simplify_path simplifies based on the filesystem, while Path.simplify is a purely syntactic simplification. In particular, when a prefix of path refers to a link, the link is resolved before a subsequent directory-navigation element is simplified, which can produce a different reference than a syntactic simplification.

The filesystem.normalize_path function is equivalent to filesystem.simplify_path(Path.to_absolute_path(path)). Note that normalization does not use Path.normal_case.

Uses Path.cleanse on path and then returns a path that references the same file or directory as path. If path refers to a soft link to another path, then the referenced path is returned (which may be a relative path with respect to the directory parent of path), otherwise the cleansed path is returned.

On Windows, the path for a link should be simplified syntactically, so that an up-directory indicator removes a preceding path element independent of whether the preceding element itself refers to a link. Beware that relative-paths links require further care.

Uses Path.cleanse on path and then, on platforms that use the #'unix path convention, checks for a leading ~ and replaces the path element starting from ~ with the path to the specified user’s home directory. A Exn.Fail.Filesystem exception is thrown if the home directory cannot be found.

When filesystem.current_force_delete_permissions has a true value (the default), then when attempting to delete a file on Windows, the files is made writable before attempting to delete it. This mode more closely imitates the behavior of file deletion on Unix.