#
Chapter 15
`file.ss`: Filesystem Utilities

See also section 11.3 in PLT MzScheme: Language Manual.

`(build-absolute-path``` `base path``` `···``)` PROCEDURE

Like `build-path` (see section 11.3 in PLT MzScheme: Language Manual), but `base` is required to be an absolute pathname. If `base` is not an absolute pathname, `error` is called.

`(build-relative-path``` `base path``` `···``)` PROCEDURE

Like `build-path` (see section 11.3 in PLT MzScheme: Language Manual), but `base` is required to be a relative pathname. If `base` is not a relative pathname, `error` is called.

`(call-with-input-file*``` `pathname proc flag-symbol``` `···``)` PROCEDURE

Like ``call-with-input-file``, except that the opened port is closed if control escapes from the body of `proc`.

`(call-with-output-file*``` `pathname proc flag-symbol``` `···``)` PROCEDURE

Like ``call-with-output-file``, except that the opened port is closed if control escapes from the body of `proc`.

`(copy-directory/files``` `src-path dest-path``)` PROCEDURE

Copies the file or directory `src-path` to `dest-path`, raising `exn:i/o:filesystem` if the file or directory cannot be copied, possibly because `dest-path` exists already. If `src-path` is a directory, the copy applies recursively to the directory's content. If a source is a link, the target of the link is copied rather than the link itself.

`(delete-directory/files``` `path``)` PROCEDURE

Deletes the file or directory specified by `path`, raising `exn:i/o:filesystem` if the file or directory cannot be deleted. If `path` is a directory, then `delete-directory/files` is first applied to each file and directory in `path` before the directory is deleted. The return value is void.

`(explode-path``` `path``)` PROCEDURE

Returns the list of directories that constitute `path`. The `path` argument must be normalized (except for letter case; see `normalize-path` below).

`(file-name-from-path``` `path``)` PROCEDURE

If `path` is a file pathname, returns just the file name part without the directory path.

`(filename-extension``` `path``)` PROCEDURE

Returns a string that is the extension part of the filename in `path`. If `path` is (syntactically) a directory, `#f` is returned.

`(find-files``` `predicate``` [`start-pathname`]`)` PROCEDURE

Traverses the filesystem starting at `start-pathname` and creates a list of all files and directories for which `predicate` returns true. If `start-pathname` is `#f` (the default), then the traversal starts from the current directory (as determined by ``current-directory``; see section 7.4.1.1 in PLT MzScheme: Language Manual).

The `predicate` procedure is called with a single argument for each file or directory. If `start-pathname` is `#f`, the argument is a pathname string that is relative to the current directory. Otherwise, it is a pathname that starts with `start-pathname`. Consequently, supplying `(`current-directory`)` for `start-pathname` is different from supplying `#f`, because `predicate` receives complete paths in the former case and relative paths in the latter. Another difference is that `predicate` is not called for the current directory when `start-pathname` is `#f`.

The `find-files` traversal follows soft links. To avoid following links, use the more general `fold-files` procedure.

If `start-pathname` does not refer to an existing file or directory, then `predicate` will be called exactly once with `start-pathname` as the argument.

`(find-library``` `name collection``)` PROCEDURE

Returns the path of the specified library (see Chapter 16 in PLT MzScheme: Language Manual), returning `#f` if the specified library or collection cannot be found. The `collection` argument is optional, defaulting to `"mzlib"`.

`(find-relative-path``` `basepath path``)` PROCEDURE

Finds a relative pathname with respect to `basepath` that names the same file or directory as `path`. Both `basepath` and `path` must be normalized (except for letter case; see `normalize-path` below). If `path` is not a proper subpath of `basepath` (i.e., a subpath that is strictly longer), `path` is returned.

`(fold-files``` `proc init-val``` [`start-pathname follow-links?`]`)` PROCEDURE

Traverses the filesystem starting at `start-pathname`, calling `proc` on each discovered file, directory, and link. If `start-pathname` is `#f` (the default), then the traversal starts from the current directory (as determined by ``current-directory``; see section 7.4.1.1 in PLT MzScheme: Language Manual).

The `proc` procedure is called with three arguments for each file, directory, or link:

- If `start-pathname` is `#f`, the first argument is a pathname string that is relative to the current directory. Otherwise, the first argument is a pathname that starts with `start-pathname`. Consequently, supplying `(`current-directory`)` for `start-pathname` is different from supplying `#f`, because `predicate` receives complete paths in the former case and relative paths in the latter. Another difference is that `proc` is not called for the current directory when `start-pathname` is `#f`.

- The second argument is a symbol, either `'file`, `'dir`, or `'link`. The second argument can be `'link` only when `follow-links?` is `#f`, in which case the filesystem traversal does not follow links. The default for `follow-links?` is `#t`.

- The third argument is the accumulated result. For the first call to `proc`, the third argument is `init-val`. For the second call to `proc` (if any), the third argument is the result from the first call, and so on. The result of the last call to `proc` is the result of `fold-files`.

If `start-pathname` does not refer to an existing file or directory, then `proc` will be called exactly once with `start-pathname` as the first argument, `'file` as the second argument, and `init-val` as the third argument.

`(get-preference``` `name``` [`failure-thunk flush-cache? filename`]`)` PROCEDURE

Extracts a preference value from the file designated by `(`find-system-path` 'pref-file)` (see section 11.3 in PLT MzScheme: Language Manual), or by `filename` if it is provided and is not `#f`. In the former case, if the preference file doesn't exist, `get-preferences` attempts to read a `plt-prefs.ss` file in the `defaults` collection, instead. If neither file exists, the preference set is empty.

The preference file should contain a symbol-keyed association list (written to the file with the default parameter settings). Keys starting with `mzscheme:`, `mred:`, and `plt:` in any letter case are reserved for use by PLT.

The result of `get-preference` is the value associated with `name` if it exists in the association list, or the result of calling `failure-thunk` otherwise. The default `failure-thunk` returns `#f`.

Preference settings from the standard preference file are cached (weakly) across calls to `get-preference`; if `flush-cache?` is provided as `#f`, the cache is used instead of the re-consulting the preferences file.

See also `put-preferences`. The `framework` collection supports a more elaborate preference system; see PLT Framework: GUI Application Framework for details.

`(make-directory*``` `path``)` PROCEDURE

Creates directory specified by `path`, creating intermediate directories as necessary.

`(make-temporary-file``` [`format-string copy-from-filename`]`)` PROCEDURE

Creates a new temporary file and returns a pathname string for the file. Instead of merely generating a fresh file name, the file is actually created; this prevents other threads or processes from picking the same temporary name; if `copy-from-filename` is provided as string, the temporary file is created as a copy of the named file,. If `copy-from-filename` is `#f` or not provided, the temporary file is created as empty.

The temporary file is not opened for reading or writing when the pathname is returned. The client program calling `make-temporary-file` is expected to open the file with the desired access and flags (probably using the `'truncate` flag; see section 11.1.2 in PLT MzScheme: Language Manual) and to delete it when it is no longer needed.

If `format-string` is specified, it must be a format string suitable for use with `format` and one additional string argument (where the string contains only digits). If the resulting string is a relative path, it is combined with the result of `(`find-system-path` 'temp-dir)`. The default `format-string` is `"mztmp~a"`.

`(normalize-path``` `path wrt``)` PROCEDURE

Returns a normalized, complete version of `path`, expanding the path and resolving all soft links. If `path` is relative, then the pathname `wrt` is used as the base path. The `wrt` argument is optional; if is omitted, then the current directory is used as the base path.

Letter case is not normalized by `normalize-path`, so combine `normalize-path` with `normal-case-path` to get strings for path comparison.

An error is signaled by `normalize-path` if the input path contains an embedded path for a non-existent directory, or if an infinite cycle of soft-links is detected.

`(path-only``` `path``)` PROCEDURE

If `path` is a filename, the file's path is returned. If `path` is syntactically a directory, `#f` is returned.

`(put-preferences``` `name-list val-list``` [`locked-proc filename`]`)` PROCEDURE

See also `get-preference`.

Installs a set of preference values and writes all current values to the preference file designated by `(`find-system-path` 'pref-file)` (see section 11.3 in PLT MzScheme: Language Manual), or `fielname` if it is supplied and not `#f`. The `name-list` argument must be a list of symbols for the preference names, and `val-list` must have the same length as `name-list`.

Current preference values are read from the preference file before updating, and an update ``lock'' is held starting before the file read, and lasting until after the preferences file is updated. The lock is implemented by the existence of a file in the same directory as the preference file.

If the update lock is already held (i.e., the lock file exists), then `locked-proc` is called with a single argument: the path of the lock file. The default `locked-proc` reports an error; an alternative thunk might wait a while and try again, or give the user the choice to delete the lock file (in case a previous update attempt encountered disaster).

If `filename` is `#f` or not supplied, and the preference file does not already exist, then values read from the `defaults` collection (if any) are written for preferences that are not mentioned in `name-list`.