On this page:
14.2.1 Locating Paths
find-system-path
path-list-string->path-list
find-executable-path
14.2.2 Files
file-exists?
link-exists?
delete-file
rename-file-or-directory
file-or-directory-modify-seconds
file-or-directory-permissions
file-or-directory-identity
file-size
copy-file
make-file-or-directory-link
14.2.3 Directories
current-directory
current-drive
directory-exists?
make-directory
delete-directory
directory-list
filesystem-root-list
14.2.4 Declaring Paths Needed at Run Time
define-runtime-path
define-runtime-paths
define-runtime-path-list
define-runtime-module-path
runtime-paths
14.2.5 More File and Directory Utilities
file->string
file->bytes
file->value
file->list
file->lines
file->bytes-lines
display-to-file
write-to-file
display-lines-to-file
copy-directory/ files
delete-directory/ files
find-files
pathlist-closure
fold-files
make-directory*
make-temporary-file
get-preference
put-preferences

14.2 Filesystem

14.2.1 Locating Paths

(find-system-path kind)  path?
  kind : symbol?
Returns a machine-specific path for a standard type of path specified by kind, which must be one of the following:

(path-list-string->path-list str 
  default-path-list) 
  (listof path?)
  str : (or/c string? bytes?)
  default-path-list : (listof path?)

Parses a string or byte string containing a list of paths, and returns a list of path strings. Under Unix and Mac OS X, paths in a path list are separated by a :; under Windows, paths are separated by a ;. Whenever the path list contains an empty path, the list default-path-list is spliced into the returned list of paths. Parts of str that do not form a valid path are not included in the returned list.

(find-executable-path program-sub    
  [related-sub    
  deepest?])  (or/c path? #f)
  program-sub : path-string?
  related-sub : (or/c path-string? #f) = #f
  deepest? : any/c = #f
Finds a path for the executable program-sub, returning #f if the path cannot be found.

If related-sub is not #f, then it must be a relative path string, and the path found for program-sub must be such that the file or directory related-sub exists in the same directory as the executable. The result is then the full path for the found related-sub, instead of the path for the executable.

This procedure is used by the mzscheme executable to find the standard library collection directory (see Libraries and Collections). In this case, program is the name used to start MzScheme and related is "collects". The related-sub argument is used because, under Unix and Mac OS X, program-sub may involve to a sequence of soft links; in this case, related-sub determines which link in the chain is relevant.

If related-sub is not #f, then when find-executable-path does not finds a program-sub that is a link to another file path, the search can continue with the destination of the link. Further links are inspected until related-sub is found or the end of the chain of links is reached. If deepest? is #f (the default), then the result corresponds to the first path in a chain of links for which related-sub is found (and further links are not actually explored); otherwise, the result corresponds to the last link in the chain for which related-sub is found.

If program-sub is a pathless name, find-executable-path gets the value of the PATH environment variable; if this environment variable is defined, find-executable-path tries each path in PATH as a prefix for program-sub using the search algorithm described above for path-containing program-subs. If the PATH environment variable is not defined, program-sub is prefixed with the current directory and used in the search algorithm above. (Under Windows, the current directory is always implicitly the first item in PATH, so find-executable-path checks the current directory first under Windows.)

14.2.2 Files

(file-exists? path)  boolean?
  path : path-string?
Returns #t if a file (not a directory) path exists, #f otherwise.

Under Windows, file-exists? reports #t for all variations of the special filenames (e.g., "LPT1", "x:/baddir/LPT1").

(link-exists? path)  boolean?
  path : path-string?
Returns #t if a link path exists (Unix and Mac OS X), #f otherwise.

The predicates file-exists? or directory-exists? work on the final destination of a link or series of links, while link-exists? only follows links to resolve the base part of path (i.e., everything except the last name in the path).

This procedure never raises the exn:fail:filesystem exception.

(delete-file path)  void?
  path : path-string?
Deletes the file with path path if it exists, otherwise the exn:fail:filesystem exception is raised. If path is a link, the link is deleted rather than the destination of the link.

(rename-file-or-directory old    
  new    
  [exists-ok?])  void?
  old : path-string?
  new : path-string?
  exists-ok? : any/c = #f
Renames the file or directory with path old – if it exists – to the path new. If the file or directory is not renamed successfully, the exn:fail:filesystem exception is raised.

This procedure can be used to move a file/directory to a different directory (on the same disk) as well as rename a file/directory within a directory. Unless exists-ok? is provided as a true value, new cannot refer to an existing file or directory. Even if exists-ok? is true, new cannot refer to an existing file when old is a directory, and vice versa. (If new exists and is replaced, the replacement is atomic in the filesystem, except under Windows 95, 98, or Me. However, the check for existence is not included in the atomic action, which means that race conditions are possible when exists-ok? is false or not supplied.)

If old is a link, the link is renamed rather than the destination of the link, and it counts as a file for replacing any existing new.

(file-or-directory-modify-seconds path    
  [secs-n    
  fail-thunk])  any
  path : path-string?
  secs-n : (or/c exact-integer? #f) = #f
  fail-thunk : (-> any)
   = (lambda () (raise (make-exn:fail:filesystem ....)))
Returns the file or directory’s last modification date as platform-specific seconds (see also Time) when secs-n is not provided or is #f. (For FAT filesystems under Windows, directories do not have modification dates. Therefore, the creation date is returned for a directory, but the modification date is returned for a file.)

If secs-n is provided and not #f, the access and modification times of path are set to the given time.

On error (e.g., if no such file exists), fail-thunk is called, and the default fail-thunk raises exn:fail:filesystem.

Returns a list containing 'read, 'write, and/or 'execute for the given file or directory path. On error (e.g., if no such file exists), the exn:fail:filesystem exception is raised. Under Unix and Mac OS X, permissions are checked for the current effective user instead of the real user.

(file-or-directory-identity path [as-link?])
  exact-positive-integer?
  path : path-string?
  as-link? : any/c = #f
Returns a number that represents the identity of path in terms of the device and file or directory that it accesses. This function can be used to check whether two paths correspond to the same filesystem entity under the assumption that the path’s entity selection does not change.

If as-link? is a true value, then if path refers to a filesystem link, the identity of the link is returned instead of the identity of the referenced file or directory (if any).

Returns the (logical) size of the specified file in bytes. Under Mac OS X, this size excludes the resource-fork size. On error (e.g., if no such file exists), the exn:fail:filesystem exception is raised.

(copy-file src dest)  void?
  src : path-string?
  dest : path-string?
Creates the file dest as a copy of src. If the file is not successfully copied, the exn:fail:filesystem exception is raised. If dest already exists, the copy will fail. File permissions are preserved in the copy. Under Mac OS X, the resource fork is also preserved in the copy. If src refers to a link, the target of the link is copied, rather than the link itself.

(make-file-or-directory-link to path)  void?
  to : path-string?
  path : path-string?
Creates a link path to to under Unix and Mac OS X. The creation will fail if path already exists. The to need not refer to an existing file or directory, and to is not expanded before writing the link. If the link is not created successfully,the exn:fail:filesystem exception is raised. Under Windows, the exn:fail:unsupported exception is raised always.

14.2.3 Directories

See also: rename-file-or-directory, file-or-directory-modify-seconds, file-or-directory-permissions.

A parameter that determines the current directory for resolving relative paths.

When the parameter procedure is called to set the current directory, the path argument is cleansed using cleanse-path, simplified using simplify-path, and then converted to a directory path with path->directory-path; cleansing and simplification raise an exception if the path is ill-formed. Thus, the current value of current-directory is always a cleansed, simplified, complete, directory path.

The path is not checked for existence when the parameter is set.

Returns the current drive name Windows. For other platforms, the exn:fail:unsupported exception is raised. The current drive is always the drive of the current directory.

(directory-exists? path)  boolean?
  path : path-string?
Returns #t if path refers to a directory, #f otherwise.

(make-directory path)  void?
  path : path-string?
Creates a new directory with the path path. If the directory is not created successfully, the exn:fail:filesystem exception is raised.

(delete-directory path)  void?
  path : path-string?
Deletes an existing directory with the path path. If the directory is not deleted successfully, the exn:fail:filesystem exception is raised.

(directory-list [path])  (listof path?)
  path : path-string? = (current-directory)
Returns a list of all files and directories in the directory specified by path. If path is omitted, a list of files and directories in the current directory is returned. Under Unix and Mac OS X, an element of the list can start with ./~ if it would otherwise start with ~. Under Windows, an element of the list may start with \\?\REL\\.

Returns a list of all current root directories. Obtaining this list can be particularly slow under Windows.

14.2.4 Declaring Paths Needed at Run Time

The bindings documented in this section are provided by the scheme/runtime-path library, not scheme/base or scheme.

The scheme/runtime-path library provides forms for accessing files and directories at run time using a path that are usually relative to an enclosing source file. Unlike using collection-path, define-runtime-path exposes each run-time path to tools like the executable and distribution creators, so that files and directories needed at run time are carried along in a distribution.

In addition to the bindings described below, scheme/runtime-path provides #%datum in phase level 1, since string constants are often used as compile-time expressions with define-runtime-path.

Uses expr as both a compile-time (i.e., phase 1) expression and a run-time (i.e., phase 0) expression. In either context, expr should produce a path, a string that represents a path, a list of the form (list 'lib str ...+), or a list of the form (list 'so str).

For run time, id is bound to a path that is based on the result of expr. The path is normally computed by taking a relative path result from expr and adding it to a path for the enclosing file (which is computed as described below). However, tools like the executable creator can also arrange (by colluding with scheme/runtime-path) to have a different base path substituted in a generated executable. If expr produces an absolute path, it is normally returned directly, but again may be replaced by an executable creator. In all cases, the executable creator preserves the relative locations of all paths. When expr produces a relative or absolute path, then the path bound to id is always an absolute path.

If expr produces a list of the form (list 'lib str ...+), the value bound to id is an absolute path. The path refers to a collection-based file similar to using the value as a module path.

If expr produces a list of the form (list 'so str), the value bound to id can be either str or an absolute path; it is an absolute path when adding the platform-specific shared-library extension – as produced by (system-type 'so-suffix) – and then searching in the PLT-specific shared-object library directories (as determined by get-lib-search-dirs) locates the path. In this way, shared-object libraries that are installed specifically for PLT Scheme get carried along in distributions.

For compile-time, the expr result is used by an executable creator – but not the result when the containing module is compiled. Instead, expr is preserved in the module as a compile-time expression (in the sense of begin-for-syntax). Later, at the time that an executable is created, the compile-time portion of the module is executed (again), and the result of expr is the file to be included with the executable. The reason for the extra compile-time execution is that the result of expr might be platform-dependent, so the result should not be stored in the (platform-independent) bytecode form of the module; the platform at executable-creation time, however, is the same as at run time for the executable. Note that expr is still evaluated at run-time; consequently, avoid procedures like collection-path, which depends on the source installation, and instead use relative paths and forms like (list 'lib str ...+).

If a path is needed only on some platforms and not on others, use define-runtime-path-list with an expr that produces an empty list on platforms where the path is not needed.

The enclosing path for a define-runtime-path is determined as follows from the define-runtime-path syntactic form:

In the latter two cases, the path is normally preserved in (platform-specific) byte form. If it is is within the result of find-collects-dir, however, it the path is recorded relative to (find-collects-dir), and it is reconstructed using (find-collects-dir) at run time.

Examples:

  ; Access a file "data.txt" at run-time that is originally
  ; located in the same directory as the module source file:
  (define-runtime-path data-file "data.txt")
  (define (read-data)
    (with-input-from-file data-file
      (lambda ()
        (read-bytes (file-size data-file)))))
  
  ; Load a platform-specific shared object (using ffi-lib)
  ; that is located in a platform-specific sub-directory of the
  ; module's source directory:
  (define-runtime-path libfit-path
    (build-path "compiled" "native" (system-library-subpath #f)
                (path-replace-suffix "libfit"
                                     (system-type 'so-suffix))))
  (define libfit (ffi-lib libfit-path))
  
  ; Load a platform-specific shared object that might be installed
  ; as part of the operating system, or might be installed
  ; specifically for PLT Scheme:
  (define-runtime-path libssl-so
    (case (system-type)
      [(windows) '(so "ssleay32")]
      [else '(so "libssl")]))
  (define libssl (ffi-lib libssl-so))

(define-runtime-paths (id ...) expr)
Like define-runtime-path, but declares and binds multiple paths at once. The expr should produce as many values as ids.

Like define-runtime-path, but expr should produce a list of paths.

(define-runtime-module-path id module-path)
Similar to define-runtime-path, but id is bound to a resolved module path. The resolved module path for id corresponds to module-path (with the same syntax as a module path for require), which can be relative to the enclosing module.

Use define-runtime-module-path to bind a module path that is passed to a reflective function like dynamic-require while also creating a module dependency for building and distributing executables.

The define-runtime-module-path form creates a for-label dependency from an enclosing module to module-path. Since the dependency is merely for-label, module-path is not instantiated or visited when the enclosing module is instantiated or visited (unless such a dependency is created by other requires).

(runtime-paths module-path)
This form is mainly for use by tools such as executable builders. It expands to a quoted list containing the run-time paths declared by module-path, returning the compile-time results of the declaration exprs, except that paths are converted to byte strings. The enclosing module must require (directly or indirectly) the module specified by module-path, which is an unquoted module path. The resulting list does not include module paths bound through define-runtime-module-path.

14.2.5 More File and Directory Utilities

The bindings documented in this section are provided by the scheme/file and scheme libraries, but not scheme/base.

(file->string path [#:mode mode-flag])  string?
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
Reads all characters from path and returns them as a string. The mode-flag argument is the same as for open-input-file.

(file->bytes path [#:mode mode-flag])  bytes?
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
Reads all characters from path and returns them as a byte string. The mode-flag argument is the same as for open-input-file.

(file->value path [#:mode mode-flag])  bytes?
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
Reads a single S-expression from path using read. The mode-flag argument is the same as for open-input-file.

(file->list path [proc #:mode mode-flag])  (listof any/c)
  path : path-string?
  proc : (input-port? . -> . any/c) = read
  mode-flag : (or/c 'binary 'text) = 'binary
Repeatedly calls proc to consume the contents of path, until eof is produced. The mode-flag argument is the same as for open-input-file.

(file->lines path    
  [#:mode mode-flag    
  #:line-mode line-mode])  (listof string?)
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
  line-mode : (or/c 'linefeed 'return 'return-linefeed 'any 'any-one)
   = 'any
Read all characters from path, breaking them into lines. The line-mode argument is the same as the second argument to read-line, but the default is 'any instead of 'linefeed. The mode-flag argument is the same as for open-input-file.

(file->bytes-lines path    
  [#:mode mode-flag    
  #:line-mode line-mode])  (listof bytes?)
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
  line-mode : (or/c 'linefeed 'return 'return-linefeed 'any 'any-one)
   = 'any
Like file->lines, but reading bytes and collecting them into lines like read-bytes-line.

(display-to-file v    
  path    
  [#:mode mode-flag    
  #:exists exists-flag])  void?
  v : any/c
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
  exists-flag : 
(or/c 'error 'append 'update
      'replace 'truncate 'truncate/replace)
   = 'error
Uses display to print v to path. The mode-flag and exists-flag arguments are the same as for open-output-file.

(write-to-file v    
  path    
  [#:mode mode-flag    
  #:exists exists-flag])  void?
  v : any/c
  path : path-string?
  mode-flag : (or/c 'binary 'text) = 'binary
  exists-flag : 
(or/c 'error 'append 'update
      'replace 'truncate 'truncate/replace)
   = 'error
Like display-to-file, but using write instead of display.

(display-lines-to-file lst    
  path    
  [#:separator separator    
  #:mode mode-flag    
  #:exists exists-flag])  void?
  lst : list?
  path : path-string?
  separator : any/c = #"\n"
  mode-flag : (or/c 'binary 'text) = 'binary
  exists-flag : 
(or/c 'error 'append 'update
      'replace 'truncate 'truncate/replace)
   = 'error
Displays each element of lst to path, adding separator after each element. The mode-flag and exists-flag arguments are the same as for open-output-file.

(copy-directory/files src dest)  void?
  src : path-string?
  dest : path-string?
Copies the file or directory src to dest, raising exn:fail:filesystem if the file or directory cannot be copied, possibly because dest exists already. If src 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)  void?
  path : path-string?
Deletes the file or directory specified by path, raising exn:fail: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.

(find-files predicate [start-path])  (listof path?)
  predicate : (path? . -> . any/c)
  start-path : (or/c path-string? #f) = #f
Traverses the filesystem starting at start-path and creates a list of all files and directories for which predicate returns true. If start-path is #f, then the traversal starts from (current-directory). In the resulting list, each directory precedes its content.

The predicate procedure is called with a single argument for each file or directory. If start-path is #f, the argument is a pathname string that is relative to the current directory. Otherwise, it is a path building on start-path. Consequently, supplying (current-directory) for start-path 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-path is #f.

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

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

The find-files procedure raises and exception if it encounters a directory for which directory-list fails.

(pathlist-closure path-list)  (listof path?)
  path-list : (listof path-string?)
Given a list of paths, either absolute or relative to the current directory, returns a list such that

(fold-files proc    
  init-val    
  [start-path    
  follow-links?])  any
  proc : 
(or/c (path? (or/c 'file 'dir 'link) any/c
        . -> . any/c)
      (path? (or/c 'file 'dir 'link) any/c
        . -> . (values any/c any/c)))
  init-val : any/c
  start-path : (or/c path-string? #f) = #f
  follow-links? : any/c = #t
Traverses the filesystem starting at start-path, calling proc on each discovered file, directory, and link. If start-path is #f, then the traversal starts from (current-directory).

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

The proc argument is used in an analogous way to the procedure argument of foldl, where its result is used as the new accumulated result. There is an exception for the case of a directory (when the second argument is 'dir): in this case the procedure may return two values, the second indicating whether the recursive scan should include the given directory or not. If it returns a single value, the directory is scanned. In the cases of files or links (when the second argument is 'file or 'link), a second value is permitted but ignored.

If the start-path is provided but no such path exists, or if paths disappear during the scan, then an exception is raised.

(make-directory* path)  void?
  path : path-string?
Creates directory specified by path, creating intermediate directories as necessary.

(make-temporary-file [template    
  copy-from-filename    
  directory])  path?
  template : string? = "mztmp~a"
  copy-from-filename : (or/c path-string? #f 'directory) = #f
  directory : (or/c path-string? #f) = #f
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.

The template argument 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), unless directory is provided and non-#f, in which case the file name generated from template is combined with directory to obtain a full path.

If copy-from-filename is provided as path, the temporary file is created as a copy of the named file (using copy-file). If copy-from-filename is #f, the temporary file is created as empty. If copy-from-filename is 'directory, then the temporary “file” is created as a directory.

When a temporary file is created, it 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 open-output-file) and to delete it when it is no longer needed.

(get-preference name    
  [failure-thunk    
  flush-mode    
  filename])  any
  name : symbol?
  failure-thunk : (-> any) = (lambda () #f)
  flush-mode : any/c = 'timestamp
  filename : (or/c string-path? #f) = #f
Extracts a preference value from the file designated by (find-system-path 'pref-file), 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.

Preference settings are cached (weakly) across calls to get-preference, using (path->complete-path filename) as a cache key. If flush-mode is provided as #f, the cache is used instead of the re-consulting the preferences file. If flush-mode is provided as 'timestamp (the default), then the cache is used only if the file has a timestamp that is the same as the last time the file was read. Otherwise, the file is re-consulted.

See also put-preferences. For a more elaborate preference system, see preferences:get.

(put-preferences names    
  vals    
  [locked-proc    
  filename])  void?
  names : (listof symbol?)
  vals : list?
  locked-proc : (path? . -> . any) = (lambda (p) (error ....))
  filename : (or/c #f path-string?) = #f
Installs a set of preference values and writes all current values to the preference file designated by (find-system-path 'pref-file), or filename if it is supplied and not #f.

The names argument supplies the preference names, and vals must have the same length as names. Each element of vals must be an instance of a built-in data type whose write output is readable (i.e., the print-unreadable parameter is set to #f while writing preferences).

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 directory of the preferences file does not already exist, it is created.

If the update lock is already held (i.e., the lock file exists), then locked is called with a single argument: the path of the lock file. The default locked 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 names.