15.2 Filesystem (original) (raw)
15.2 Filesystem🔗ℹ
15.2.1 Locating Paths🔗ℹ
Returns a machine-specific path for a standard type of path specified by kind, which must be one of the following:
- 'home-dir — the current user’s home directory.
On all platforms, if the PLTUSERHOME environment variable is defined as a complete path, then the path is used as the user’s home directory.
On Unix and Mac OS, when PLTUSERHOME does not apply, the user’s home directory is determined by expanding the path "~", which is expanded by first checking for a HOME environment variable. If none is defined, the USER and LOGNAME environment variables are consulted (in that order) to find a user name, and then system files are consulted to locate the user’s home directory.
On Windows, when PLTUSERHOME does not apply, the user’s home directory is the user-specific profile directory as determined by the Windows registry. If the registry cannot provide a directory for some reason, the value of theUSERPROFILE environment variable is used instead, as long as it refers to a directory that exists. If USERPROFILEalso fails, the directory is the one specified by theHOMEDRIVE and HOMEPATH environment variables. If those environment variables are not defined, or if the indicated directory still does not exist, the directory containing the current executable is used as the home directory. - 'pref-dir — the standard directory for storing the current user’s preferences. The preferences directory might not exist.
On Unix, the preferences directory is normally the "racket"subdirectory of the path specified byXDG_CONFIG_HOME, or ".config/racket" in theuser’s home directory if XDG_CONFIG_HOME is not set to an absolute path or if PLTUSERHOME is set. Either way, if that directory does not exist but a ".racket" directory exists in the user’s home directory, then that directory is the preference directory, instead.
On Windows, the preferences directory is "Racket" in theuser’s home directory if determined by PLTUSERHOME, otherwise in the user’s application-data folder as specified by the Windows registry; the application-data folder is usually"Application Data" in the user’s profile directory.
On Mac OS, the preferences directory is"Library/Preferences" in the user’s home directory. - 'pref-file — a file that contains a symbol-keyed association list of preference values. The file’s directory path always matches the result returned for'pref-dir. The file name is "racket-prefs.rktd" on Unix and Windows, and it is "org.racket-lang.prefs.rktd" on Mac OS. The file’s directory might not exist. See alsoget-preference.
- 'temp-dir — the standard directory for storing temporary files. On Unix and Mac OS, this is the directory specified by the TMPDIR environment variable, if it is defined, otherwise it is the first path that exists among"/var/tmp", "/usr/tmp", and "/tmp". On Windows, the result is the directory specified by theTMP or TEMP environment variable, if it is defined, otherwise it is the current directory.
- 'init-dir — the directory containing the initialization file used by the Racket executable.
On Unix, the initialization directory is the same as the result returned for 'pref-dir—unless that directory does not exist and a ".racketrc" file exists in the user’s home directory, in which case the home directory is the initialization directory.
On Windows, the initialization directory is the same as theuser’s home directory.
On Mac OS, the initialization directory is "Library/Racket"in the user’s home directory—unless no"racketrc.rktl" exists there and a ".racketrc" file does exist in the home directory, in which case the home directory is the initialization directory. - 'init-file — the file loaded at start-up by the Racket executable. The directory part of the path is the same path as returned for 'init-dir.
On Windows, the file part of the name is"racketrc.rktl".
On Unix and Mac OS, the file part of the name is"racketrc.rktl"—unless the path returned for'init-dir is the user’s home directory, in which case the file part of the name is ".racketrc". - 'config-dir — a directory for the installation’s configuration. This directory is specified by thePLTCONFIGDIR environment variable, and it can be overridden by the --config or -G command-line flag. If no environment variable or flag is specified, or if the value is not a legal path name, then this directory defaults to an"etc" directory relative to the current executable. If the result of (find-system-path 'config-dir) is a relative path, it is relative to the current executable. The directory might not exist.
- 'host-config-dir — like'config-dir, but when cross-platform build mode has been selected (through the -C or --cross argument toracket; see Command Line), the result refers to a directory for the current system’s installation, instead of for the target system.
- 'addon-dir — a directory for user-specific Racket configuration, packages, and extension. This directory is specified by thePLTADDONDIR environment variable, and it can be overridden by the --addon or -A command-line flag. If no environment variable or flag is specified, or if the value is not a legal path name, then this directory defaults to a platform-specific locations. The directory might not exist.
On Unix, the default is normally the "racket" subdirectory of the path specified by XDG_DATA_HOME, or".local/share/racket" in the user’s home directory ifXDG_CONFIG_HOME is not set to an absolute path or ifPLTUSERHOME is set. If that directory does not exists but a".racket" directory exists in the user’s home directory, that the ".racket" directory path is the default, instead.
On Windows, the default is the same as the 'pref-dir directory.
On Mac OS, the default is "Library/Racket" within theuser’s home directory. - 'cache-dir — a directory for storing user-specific caches. The directory might not exist.
On Unix, the cache directory is normally the "racket"subdirectory of the path specified byXDG_CACHE_HOME, or ".cache/racket" in theuser’s home directory if XDG_CACHE_HOME is not set to an absolute path or if PLTUSERHOME is set. If that directory does not exist but a ".racket" directory exists in the home directory, then the ".racket" directory is the cache directory, instead.
On Windows, the cache directory is the same as the result returned for 'addon-dir.
On Mac OS, the cache directory is "Library/Caches/Racket"within the user’s home directory. - 'doc-dir — the standard directory for storing the current user’s documents. On Unix, it’s the user’s home directory. On Windows, it is the user’s home directory if determined by PLTUSERHOME, otherwise it is the user’s documents folder as specified by the Windows registry; the documents folder is usually "My Documents" in the user’s home directory. On Mac OS, it’s the "Documents" directory in the user’s home directory.
- 'desk-dir — the directory for the current user’s desktop. On Unix, it’s the user’s home directory. On Windows, it is the user’s home directory if determined byPLTUSERHOME, otherwise it is the user’s desktop folder as specified by the Windows registry; the desktop folder is usually"Desktop" in the user’s home directory. On Mac OS, it is"Desktop" in the user’s home directory
- 'sys-dir — the directory containing the operating system for Windows. On Unix and Mac OS, the result is "/".
- 'exec-file — the path of the Racket executable as provided by the operating system for the current invocation. For some operating systems, the path can be relative.
For GRacket, the executable path is the name of a GRacket executable.
- 'run-file — the path of the current executable; this may be different from result for'exec-file because an alternate path was provided through a--name or -N command-line flag to the Racket (or GRacket) executable, or because an embedding executable installed an alternate path. In particular a “launcher” script created by make-racket-launcher sets this path to the script’s path.
- 'collects-dir — a path to the main collection of libraries (see Libraries and Collections). If this path is relative, then it is relative to the executable as reported by(find-system-path 'exec-file)—though the latter could be a soft-link or relative to the user’s executable search path, so that the two results should be combined withfind-executable-path. The 'collects-dir path is normally embedded in the Racket executable, but it can be overridden by the --collects or -X command-line flag.
- 'host-collects-dir — like'collects-dir, but when cross-platform build mode has been selected (through the -C or --cross argument toracket; see Command Line), the result refers to a directory for the current system’s installation, instead of for the target system. In cross-platform build mode, collection files are normally read from the target system’s installation, but some tasks require current-system directories (such as the one that holds foreign libraries) that are configured relative to the main library-collection path.
- 'orig-dir — the current directory at start-up, which can be useful in converting a relative-path result from (find-system-path 'exec-file) or(find-system-path 'run-file) to a complete path.
Changed in version 6.0.0.3 of package base: Added PLTUSERHOME.
Changed in version 6.9.0.1: Added 'host-config-dirand 'host-collects-dir.
Changed in version 7.8.0.9: Added 'cache-dir, and changed to use XDG directories as preferred on Unix with the previous paths as a fallback, and with similar adjustments for Mac OS.
Parses a string or byte string containing a list of paths, and returns a list of paths. On Unix and Mac OS, paths in a path-list string are separated by a :; on Windows, paths are separated by a;, and all "s in the string are discarded. Whenever the path list contains an empty path, the listdefault-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. The given str must not contain a nul character or nul byte.
Changed in version 8.0.0.10 of package base: Changed to allow 'same indefault-path-list.
Finds a path for the executable program, returning#f if the path cannot be found.
On Windows, if program is not found and it has no file extension, then the search starts over with ".exe" added toprogram, and the result is #f only if the path with".exe" also cannot be found. The result includes the extension ".exe" if only program with the extension is found.
If related is not #f, then it must be a relative path string, and the path found for program must be such that the file or directory related exists in the same directory as the executable. The result is then the full path for the found related, instead of the path for the executable.
This procedure is used by the Racket executable to find the standard library collection directory (see Libraries and Collections). In this case, program is the name used to start Racket andrelated is "collects". The relatedargument is used because, on Unix and Mac OS, program may involve a sequence of soft links; in this case,related determines which link in the chain is relevant.
If related is not #f, then whenfind-executable-path does not find a programthat is a link to another file path, the search can continue with the destination of the link. Further links are inspected untilrelated 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 whichrelated is found (and further links are not actually explored); otherwise, the result corresponds to the last link in the chain for which related is found.
If program is a pathless name,find-executable-path gets the value of thePATH environment variable; if this environment variable is defined, find-executable-path tries each path inPATH as a prefix for program using the search algorithm described above for path-containingprograms. If the PATH environment variable is not defined, program is prefixed with the current directory and used in the search algorithm above. (On Windows, the current directory is always implicitly the first item inPATH, so find-executable-path checks the current directory first on Windows.)
Changed in version 8.1.0.7 of package base: Added search with ".exe"on Windows.
15.2.2 Files🔗ℹ
Returns #t if a file (not a directory) path exists,#f otherwise.
On Windows, file-exists? reports #t for all variations of the special filenames (e.g., "LPT1","x:/baddir/LPT1").
Returns #t if a link path exists,#f otherwise.
The predicates file-exists? or directory-exists?work on the final destination of a link or series of links, whilelink-exists? only follows links to resolve the base part ofpath (i.e., everything except the last name in the path).
This procedure never raises the exn:fail:filesystemexception.
On Windows, link-exists? reports #t for both symbolic links and junctions.
Changed in version 6.0.1.12 of package base: Added support for links on Windows.
(file-or-directory-type path [must-exist?]) → (or/c 'file 'directory 'link 'directory-link #f) path : path-string? must-exist? : any/c = #f
Reports whether path refers to a file, directory, link, or directory link (in the case of Windows; see alsomake-file-or-directory-link), assuming that path can be accessed.
If path cannot be accessed, the result is #f ifmust-exist? is #f, otherwise theexn:fail:filesystem exception is raised.
Added in version 7.8.0.5 of package base.
Deletes the file with path path if it exists, otherwise theexn:fail:filesystem exception is raised. If path is a link, the link is deleted rather than the destination of the link.
On Windows, if an initial attempt to delete the file fails with a permission error and the value ofcurrent-force-delete-permissions is true, thendelete-file attempts to change the file’s permissions (to allow writes) and then delete the file; the permission change followed by deletion is a non-atomic sequence, with no attempt to revert a permission change if the deletion fails.
On Windows, delete-file can delete a symbolic link, but not a junction. Use delete-directory to delete a junction.
On Windows, beware that if a file is deleted while it remains in use by some process (e.g., a background search indexer), then the file’s content will eventually go away, but the file’s name remains occupied until the file is no longer used. As long as the name remains occupied, attempts to open, delete, or replace the file will trigger a permission error (as opposed to a file-exists error). A common technique to avoid this pitfall is to move the file to a generated temporary name before deleting it. See alsodelete-directory/files.
Changed in version 6.1.1.7 of package base: Changed Windows behavior to usecurrent-force-delete-permissions.
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 filesystem) 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, but the check is not atomic with the rename operation on Unix and Mac OS. Even ifexists-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 on Unix and Mac OS, but it is not guaranteed to be atomic on Windows. Furthermore, if new exists and is opened by any process for reading or writing, then attempting to replace it will typically fail on Windows. See also call-with-atomic-output-file.
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.
On Windows, beware that a directory cannot be renamed if any file within the directory is open. That constraint is particularly problematic if a search indexer is running in the background (as in the default Windows configuration). A possible workaround is to combine copy-directory/files anddelete-directory/files, since the latter can deal with open files, although that sequence is obviously not atomic and temporarily duplicates files.
Returns the file or directory’s last modification date in seconds since the epoch (see also Time) whensecs-n is not provided or is #f.
For FAT filesystems on 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), then fail-thunk is called (through a tail call) to produce the result of thefile-or-directory-modify-seconds call. If fail-thunk is not provided, an error raises exn:fail:filesystem.
When given one argument or #f as the second argument, returns a list containing 'read, 'write, and/or 'execute to indicate permission the given file or directory path by the current user and group. On Unix and Mac OS, permissions are checked for the current effective user instead of the real user.
If 'bits is supplied as the second argument, the result is a platform-specific integer encoding of the file or directory properties (mostly permissions), and the result is independent of the current user and group. The lowest nine bits of the encoding are somewhat portable, reflecting permissions for the file or directory’s owner, members of the file or directory’s group, or other users:
- #o400 : owner has read permission
- #o200 : owner has write permission
- #o100 : owner has execute permission
- #o040 : group has read permission
- #o020 : group has write permission
- #o010 : group has execute permission
- #o004 : others have read permission
- #o002 : others have write permission
- #o001 : others have execute permission
See also user-read-bit, etc. On Windows, permissions from all three (owner, group, and others) are always the same, and read and execute permission are always available. On Unix and Mac OS, higher bits have a platform-specific meaning.
If an integer is supplied as the second argument, it is used as an encoding of properties (mostly permissions) to install for the file.
In all modes, the exn:fail:filesystem exception is raised on error (e.g., if no such file exists).
Returns a hash with the following keys and values, where each value currently is a nonnegative exact integer:
- 'device-id : device ID
- 'inode : inode number
- 'mode : mode bits (see below)
- 'hardlink-count : number of hard links
- 'user-id : numeric user ID of owner
- 'group-id : numeric group ID of owner
- 'device-id-for-special-file : device ID (if special file)
- 'size : size of file or symbolic link in bytes
- 'block-size : size of filesystem blocks
- 'block-count : number of used filesystem blocks
- 'access-time-seconds : last access time in seconds since the epoch
- 'modify-time-seconds : last modification time in seconds since the epoch
- 'change-time-seconds : last status change time in seconds since the epoch
- 'creation-time-seconds : creation time in seconds sincethe epoch
- 'access-time-nanoseconds : last access time in nanoseconds since the epoch
- 'modify-time-nanoseconds : last modification time in nanoseconds since the epoch
- 'change-time-nanoseconds : last status change time in nanoseconds since the epoch
- 'creation-time-nanoseconds : creation time in nanoseconds since the epoch
If as-link? is a true value, then if path refers to a symbolic link, the stat information of the link is returned instead of the stat information of the referenced filesystem item.
The mode bits are the bits for permissions and other data, as returned from the Posix stat/lstat functions or the Windows _wstat64 function, respectively. To select portions of the bit pattern, use the constantsuser-read-bit, etc.
Depending on the operating system and filesystem, the “nanoseconds” timestamps may have less than nanoseconds precision. For example, in one environment a timestamp may be 1234567891234567891 (nanoseconds precision) and in another environment 1234567891000000000 (seconds precision).
Values that aren’t available for a platform/filesystem combination may be set to 0. For example, this applies to the 'user-id and'group-id keys on Windows. Also, Posix platforms provide the status change timestamp, but not the creation timestamp; for Windows it’s the opposite.
If as-link? is #f and path isn’t accessible, the exn:fail:filesystem exception is raised. This exception is also raised ifas-link? is a true value and path can’t be resolved, i.e., is a dangling link.
Added in version 8.3.0.7 of package base.
Returns a number that represents the identity ofpath 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. On Mac OS, 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 [exists-ok?/pos #:exists-ok? exists-ok? #:permissions permissions #:replace-permissions? replace-permissions?]) → void? src : path-string? dest : path-string? exists-ok?/pos : any/c = #f exists-ok? : any/c = exists-ok?/pos permissions : (or/c #f (integer-in 0 65535)) = #f replace-permissions? : any/c = #t
Creates the file dest as a copy of src, ifdest does not already exist. If dest already exists and exists-ok? is #f, the copy fails and theexn:fail:filesystem:exists? exception is raised; otherwise, if destexists, its content is replaced with the content of src.
If src refers to a link, the target of the link is copied, rather than the link itself. If dest refers to a link andexists-ok? is true, the target of the link is updated.
File permissions are transferred from src to dest, unless permissions is supplied as non-#f on Unix and Mac OS, in which case permissions is used for dest. Beware that permissions are transferred without regard for the process’s umask setting by default, but seereplace-permissions? below. On Windows, the modification time of src is also transferred to dest; ifpermissions is supplied as non-#f, then after copying, dest is set to read-only or not depending on whether the #o2 bit is present in permissions.
The replace-permissions? argument is used only on Unix and Mac OS. When dests is created, it is created withpermissions or the permissions of src; however, the process’s umask may unset bits in the requested permissions. Whendest already exists (and exists-ok? is true), then the permissions of dest are initially left as-is. Finally, when replace-permissions? is a true value, then the permissions of dest are set after the file content is copied to permissions or the permissions of src, without modification by umask.
The exists-ok?/pos by-position argument is for backward compatibility. That by-position argument can be supplied, or theexists-ok? keyword argument can be supplied, but theexn:fail:contract exception is raised if both are supplied.
Changed in version 8.7.0.9 of package base: Added #:exists-ok?,#:permissions, and#:replace-permissions?arguments.
Creates a link path to to. The creation will fail if path already exists. The toneed 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.
On Windows XP and earlier, the exn:fail:unsupported exception is raised. On later versions of Windows, the creation of links tends to be disallowed by security policies. Windows distinguishes between file and directory links, and a directory link is created only ifto parses syntactically as a directory (seepath->directory-path). Furthermore, a relative-path link is parsed specially by the operating system; see Windows Pathsfor more information. When make-file-or-directory-linksucceeds, it creates a symbolic link as opposed to a junction or hard link. Beware that directory links must be deleted usingdelete-directory instead of delete-file.
Changed in version 6.0.1.12 of package base: Added support for links on Windows.
A parameter that determines on Windows whetherdelete-file and delete-directory attempt to change a file or directory’s permissions to delete it. The default value is#t.
15.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.
On Unix and Mac OS, the initial value of the parameter for a Racket process is taken from the PWD environment variable—if the value of the environment variable identifies the same directory as the operating system’s report of the current directory.
Like current-directory, but for use only bysrcloc->string for reporting paths relative to a directory.
Normally, current-directory-for-user should stay at its initial value, reflecting the directory where a user started a process. A tool such as DrRacket, however, implicitly lets a user select a directory (for the file being edited), in which case updatingcurrent-directory-for-user makes sense.
Returns the current drive name Windows. For other platforms, theexn:fail:unsupported exception is raised. The current drive is always the drive of the current directory.
Returns #t if path refers to a directory,#f otherwise.
Creates a new directory with the path path. If the directory is not created successfully, the exn:fail:filesystem exception is raised.
The permissions argument specifies the permissions of the created directory, where an integer representation of permissions is treated the same as for file-or-directory-permissions. On Unix and Mac OS, these permissions bits are combined with the process’s umask. On Windows, permissions is not used.
Changed in version 8.3.0.5 of package base: Added the permissions argument.
Deletes an existing directory with the path path. If the directory is not deleted successfully, theexn:fail:filesystem exception is raised.
On Windows, if an initial attempt to delete the directory fails with a permission error and the value of current-force-delete-permissionsis true, then delete-file attempts to change the directory’s permissions (to allow writes) and then delete the directory; the permission change followed by deletion is a non-atomic sequence, with no attempt to revert a permission change if the deletion fails.
Changed in version 6.1.1.7 of package base: Changed Windows behavior to usecurrent-force-delete-permissions.
Returns a list of all files and directories in the directory specified by path. If build? is #f, the resulting paths are all path elements; otherwise, the individual results are combined with path using build-path. On Windows, an element of the result list may start with\\?\REL\\.
The resulting paths are always sorted using path<?.
Returns a list of all current root directories. Obtaining this list can be particularly slow on Windows.
15.2.4 Detecting Filesystem Changes🔗ℹ
Many operating systems provide notifications for filesystem changes, and those notifications are reflected in Racket by filesystem change events.
Returns #t if v is a filesystem change event, #f otherwise.
- If path refers to a file, the event becomesready for synchronization when the file’s content or attributes change, or when the file is deleted.
- If path refers to a directory, the event becomesready for synchronization if a file or subdirectory is added, renamed, or removed within the directory.
The event also becomes ready for synchronization if it is passed to filesystem-change-evt-cancel.
Finally, depending on the precision of information available from the operating system, the event may become ready for synchronization under other circumstances. For example, on Windows, an event for a file becomes ready when any file changes within in the same directory as the file.
After a filesystem change event becomes ready for synchronization, it stays ready for synchronization. The event’s synchronization result is the event itself.
If the current platform does not support filesystem-change notifications, then the exn:fail:unsupported exception is raised iffailure-thunk is not provided as a procedure, or failure-thunk is called in tail position if provided. Similarly, if there is any operating-system error when creating the event (such as a non-existent file), then the exn:fail:filesystem exception is raised or failure-thunkis called.
Creation of a filesystem change event allocates resources at the operating-system level. The resources are released at latest when the event is sychronized and ready for synchronization, when the event is canceled with filesystem-change-evt-cancel, or when the garbage collector determine that the filesystem change event is unreachable. See also system-type in 'fs-change mode.
A filesystem change event is placed under the management of thecurrent custodian when it is created. If the custodianis shut down, filesystem-change-evt-cancel is applied to the event.
Changed in version 7.3.0.8 of package base: Allow #f for failure-thunk.
Causes evt to become immediately ready for synchronization, whether it was ready or not before, and releases the resources (at the operating-system level) for tracking filesystem changes.
15.2.5 Declaring Paths Needed at Run Time🔗ℹ
The bindings documented in this section are provided by the racket/runtime-path library, not racket/base or racket.
The racket/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 usingcollection-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,racket/runtime-path provides #%datum inphase level 1, since string constants are often used as compile-time expressions with define-runtime-path.
(define-runtime-path id maybe-runtime?-id expr) maybe-runtime?-id = | #:runtime?-id runtime?-id
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) or (list 'so str vers). If runtime?-id is provided, then it is bound in the context of expr to #f for the compile-time instance ofexpr and #t for the run-time instance of expr.
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 withracket/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 within a givenpackage (treating paths outside of any package as being together). 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 amodule path.
If expr produces a list of the form (list 'so str)or (list 'so str vers), the value bound to id can be either str or an absolute path; it is an absolute path when searching in the Racket-specific shared-object library directories (as determined byget-lib-search-dirs) locates the path. In this way, shared-object libraries that are installed specifically for Racket get carried along in distributions. The search tries each directory in order; within a directory, the search tries using str directly, then it tries adding each version specified by vers—which defaults to '(#f)—along with a platform-specific shared-library extension—as produced by(system-type 'so-suffix). A verscan be a string, or it can be a list of strings and #f.
If expr produces a list of the form (list 'share str), the value bound to id can be either str or an absolute path; it is an absolute path when searching in the directories reported by find-user-share-dir andfind-share-dir (in that order) locates the path. In this way, files that are installed in Racket’s "share" directory get carried along in distributions.
If expr produces a list of the form (list 'module module-path var-ref) or (list 'so str (list str-or-false ...)), the value bound to id is amodule path index, where module-path is treated as relative (if it is relative) to the module that is the home of thevariable reference var-ref, where var-refcan be #f if module-path is absolute. In an executable, the corresponding module is carried along, including all of its dependencies.
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 ofbegin-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 or directory 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 likecollection-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, usedefine-runtime-path-list with an expr that produces an empty list on platforms where the path is not needed.
Beware that if expr produces the path of a directory when creating an executable, the directory’s full content (including any subdirectories) is included with the executable or eventual distribution.
Also beware that define-runtime-path in a phase level other than 0 does not cooperate properly with an executable creator. To work around that limitation, put define-runtime-path in a separate module—perhaps a submodule created by module—then export the definition, and then the module containing the definition can be required into any phase level. Usingdefine-runtime-path in a phase level other than 0 logs a warning at expansion time.
The enclosing path for a define-runtime-path is determined as follows from the define-runtime-path syntactic form:
- If the form has a source module according tosyntax-source-module, then the source location is determined by preserving the original expression as a syntax object, extracting its source module path at run time (again using syntax-source-module), and then resolving the resulting module path index. Note that syntax-source-moduleis based on a syntax object’s lexical information, not its source location.
- If the expression has no source module, thesyntax-source location associated with the form is used, if is a string or path.
- If no source module is available, and syntax-sourceproduces no path, then current-load-relative-directoryis used if it is not #f. Finally,current-directory is used if all else fails.
In the latter two cases, the path is normally preserved in (platform-specific) byte form, but if the enclosing path corresponds to a result of collection-file-path, then the path is record as relative to the corresponding module path.
Changed in version 6.0.1.6 of package base: Preserve relative paths only within a package.
Changed in version 7.5.0.7: Added support for 'share in expr.
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 Racket: (define-runtime-path libssl-so (case (system-type) [(windows) '(so "ssleay32")] [else '(so "libssl")])) (define libssl (ffi-lib libssl-so))
Changed in version 6.4 of package base: Added #:runtime?-id.
(define-runtime-paths (id ...) maybe-runtime?-id expr)
Like define-runtime-path, but declares and binds multiple paths at once. The expr should produce as many values asids.
(define-runtime-path-list id maybe-runtime?-id expr)
Like define-runtime-path, but expr should produce a list of paths.
(define-runtime-module-path-index id maybe-runtime?-id module-path-expr)
Similar to define-runtime-path, but id is bound to amodule path index that encapsulates the result ofmodule-path-expr relative to the enclosing module.
Use define-runtime-module-path-index 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.
(runtime-require module-path)
Similar to define-runtime-module-path-index, but creates the distribution dependency without binding a module path index. Whenruntime-require is used multiple times within a module with the same module-path, all but the first use expands to an empty begin.
(define-runtime-module-path id module-path)
Similar to define-runtime-path, but id is bound to aresolved module path. The resolved module path forid corresponds to module-path (with the same syntax as a module path for require), which can be relative to the enclosing module.
The define-runtime-module-path-index form is usually preferred, because it creates a weaker link to the referenced module. Unlike define-runtime-module-path-index, thedefine-runtime-module-path form creates a for-labeldependency from an enclosing module to module-path. Since the dependency is merely for-label, module-path is notinstantiated or visited when the enclosing module isinstantiated or visited (unless such a dependency is created by other requires), but the code for the referenced module is loaded when the enclosing module is loaded.
(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 bymodule-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.
15.2.6 More File and Directory Utilities🔗ℹ
The bindings documented in this section are provided by the racket/file and racket libraries, but not racket/base.
Reads all characters from path and returns them as a string. The mode-flag argument is the same as foropen-input-file.
Reads all characters from path and returns them as abyte string. The mode-flag argument is the same as for open-input-file.
Reads a single S-expression from path using read. The mode-flag argument is the same as foropen-input-file.
Repeatedly calls proc to consume the contents ofpath, until eof is produced. The mode-flagargument 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. Theline-mode argument is the same as the second argument toread-line, but the default is 'any instead of'linefeed. The mode-flag argument is the same as foropen-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 andexists-flag arguments are the same as foropen-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
(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, addingseparator after each element. The mode-flag andexists-flag arguments are the same as foropen-output-file.
Copies the file or directory src to dest, raisingexn:fail:filesystem if the file or directory cannot be copied, possibly because dest exists already. If srcis a directory, the copy applies recursively to the directory’s content. If a source is a link and preserve-links? is #f, the target of the link is copied rather than the link itself; ifpreserve-links? is #t, the link is copied.
If keep-modify-seconds? is #f, then file copies keep only the properties kept by copy-file. Ifkeep-modify-seconds? is true, then each file copy also keeps the modification date of the original.
Changed in version 6.3 of package base: Added the #:preserve-links? argument.
Deletes the file or directory specified by path, raisingexn:fail:filesystem if the file or directory cannot be deleted. If path is a directory, thendelete-directory/files is first applied to each file and directory in path before the directory is deleted.
If must-exist? is true, then exn:fail:filesystem is raised if path does not exist. If must-exist? is false, then delete-directory/files succeeds if pathdoes not exist (but a failure is possible if path initially exists and is removed by another thread or process beforedelete-directory/files deletes it).
On Windows, delete-directory/files attempts to move a file into the temporary-file directory before deleting it, which avoids problems caused by deleting a file that is currently open (e.g., by a search indexer running as a background process). If the move attempt fails (e.g., because the temporary directory is on a different drive than the file), then the file is deleted directly withdelete-file.
Changed in version 7.0 of package base: Added Windows-specific file deletion.
(find-files predicate [start-path #:skip-filtered-directory? skip-filtered-directory? #:follow-links? follow-links?]) → (listof path?) predicate : (path? . -> . any/c) start-path : (or/c path-string? #f) = #f skip-filtered-directory? : any/c = #f follow-links? : any/c = #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 onstart-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.
If skip-filtered-directory? is true, then whenpredicate returns #f for a directory, the directory’s content is not traversed.
If follow-links? is true, the find-files traversal follows links, and links are not included in the result. Iffollow-links? is #f, then links are not followed, and links are included in the result.
If start-path does not refer to an existing file or directory, then predicate will be called exactly once withstart-path as the argument.
The find-files procedure raises an exception if it encounters a directory for which directory-list fails.
Changed in version 6.3.0.11 of package base: Added the#:skip-filtered-directory?argument.
Given a list of paths, either absolute or relative to the current directory, returns a list such that
- if a nested path is given, all of its ancestors are also included in the result (but the same ancestor is not added twice);
- if a path refers to directory, all of its descendants are also included in the result, except as omitted by path-filter;
- ancestor directories appear before their descendants in the result list, as long as they are not misordered in the givenpath-list.
If path-filter is a procedure, then it is applied to each descendant of a directory. If path-filter returns#f, then the descendant (and any of its descendants, in the case of a subdirectory) are omitted from the result.
If follow-links? is true, then the traversal of directories and files follows links, and the link paths are not included in the result. If follow-links? is #f, then the result list includes paths to link and the links are not followed.
Changed in version 6.3.0.11 of package base: Added the #:path-filter argument.
Traverses the filesystem starting at start-path, callingproc on each discovered file, directory, and link. Ifstart-path is #f, then the traversal starts from(current-directory).
The proc procedure is called with three arguments for each file, directory, or link:
- If start-path 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 withstart-path. Consequently, supplying(current-directory) for start-path is different from supplying #f, because proc 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-path is #f.
- The second argument is a symbol, either 'file,'dir, or 'link. The second argument can be'link when follow-links? is #f, in which case the filesystem traversal does not follow links. Iffollow-links? is #t, then procwill only get a 'link as a second argument when it encounters a dangling symbolic link (one that does not resolve to an existing file or directory).
- 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 toproc is the result of fold-files.
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.
Creates directory specified by path, creating intermediate directories as necessary, and never failing if path exists already.
If path is a relative path and the current directory does not exist, then make-directory* will not create the current directory, because it considers only explicit elements ofpath.
Creates the parent directory of the path specified by path, creating intermediate directories as necessary, and never failing if an ancestor of path exists already.
If path is a filesystem root or a relative path with a single path element, then no directory is created. Likemake-directory*, if path is a relative path and the current directory does not exist, then make-parent-directory*will not create it.
Added in version 6.1.1.3 of package base.
Creates a new temporary file and returns its path. 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 (which will contain only digits). By default, if template produces a relative path, it is combined with the result of(find-system-path 'temp-dir) usingbuild-path; alternatively, template may produce an absolute path, in which case(find-system-path 'temp-dir) is not consulted. Ifbase-dir is provided and non-#false,template must not produce a complete path, and base-dir will be used instead of(find-system-path 'temp-dir). Usingbase-dir is generally more reliable than including directory components in template: it avoids subtle bugs from manipulating paths as string and eleminates the need to sanitize format escape sequences.
On Windows, template may produce an absolute path which is not a complete path (see Windows Paths) when base-dir is absent or #f (in which case it will be resolved relative to(current-directory)) or if base-dir is a drive specification (in which case it will be used as withbuild-path). If base-dir is any other kind of path, it is an error for template to produce an absolute path.
When the template argument is not provided, if there is source location information for the callsite ofmake-temporary-file, a template string is generated based on the source location: the default is"rkttmp~a" only when no source location information is available (e.g. if make-temporary-file is used in a higher-order position).
If copy-from is provided as path, the temporary file is created as a copy of the named file (using copy-file). Ifcopy-from is #f, the temporary file is created as empty. As a special case, for backwards compatibility, if copy-from is 'directory, then the temporary “file” is created as a directory: for clarity, prefer make-temporary-directory for creating temporary directories.
When a temporary file is created, it is not opened for reading or writing when the path is returned. The client program callingmake-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.
The by-position arguments compat-copy-from andcompat-base-dir are for backwards compatibility: if provided, they take precedence over the #:copy-from and#:base-dir keyword variants. Supplying by-position arguments prevents make-temporary-filefrom generating a template using the source location.
Changed in version 8.4.0.3 of package base: Added the #:copy-from and #:base-dir arguments.
Like make-temporary-file, but creates a directory, rather than a regular file.
As with make-temporary-file, if thetemplate argument is not provided, a template string is generated from the source location of the call tomake-temporary-directory when possible: the default is "rkttmp~a" only when no source location information is available.
Added in version 8.4.0.3 of package base.
Like make-temporary-file andmake-temporary-directory, respectively, but, rather than using a template for format, the path is based on (bytes-append prefix generated suffix), wheregenerated is a byte string chosen by the implementation to produce a unique path. If there is source location information for the callsite ofmake-temporary-file* ormake-temporary-directory*, generated will incorporate that information. The resulting path is combined with base-dir as with make-temorary-file.
Added in version 8.4.0.3 of package base.
Opens a temporary file for writing in the same directory asfile, calls proc to write to the temporary file, and then atomically (except on Windows) moves the temporary file in place of file. The move simply uses rename-file-or-directory on Unix and Mac OS, and it uses rename-file-or-directory on Windows if rename-fail-handler is provided; otherwise, on Windows, the moves uses an extra rename step (see below) on Windows to avoid problems due to concurrent readers of file.
The proc function is called with an output port for the temporary file, plus the path of the temporary file. The result ofproc is the result of call-with-atomic-output-file.
The call-with-atomic-output-file function arranges to delete temporary files on exceptions.
Windows prevents programs from deleting or replacing files that are open, but it allows renaming of open files. Therefore, on Windows,call-with-atomic-output-file by default creates a second temporary file extra-tmp-file, renames file toextra-tmp-file, renames the temporary file written byproc to file, and finally deletesextra-tmp-file. Since that process is not atomic, however,rename-file-or-directory is used ifrename-fail-handler is provided, whererename-file-or-directory has some chance of being atomic, since that the source and destination of the moves will be in the same directory; any filesystem exception while attempting to rename the file is send to rename-fail-handler, which can re-raise the exception or simply return to try again, perhaps after a delay. In addition to a filesystem exception, therename-fail-handler procedure also receives the temporary file path to be moved to path. Therename-fail-handler argument is used only on Windows.
Changed in version 7.1.0.6 of package base: Added the #:rename-fail-handler argument.
(get-preference name [failure-thunk flush-mode filename #:use-lock? use-lock? #:timeout-lock-there timeout-lock-there #:lock-there lock-there]) → any name : symbol? failure-thunk : (-> any) = (lambda () #f) flush-mode : any/c = 'timestamp filename : (or/c path-string? #f) = #f use-lock? : any/c = #t timeout-lock-there : (or/c (path? . -> . any) #f) = #f lock-there : (or/c (path? . -> . any) #f) = (make-handle-get-preference-locked 0.01 name failure-thunk flush-mode filename #:lock-there timeout-lock-there)
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 an old preferences file, and then a"racket-prefs.rktd" file in the configuration directory (as reported by find-config-dir), instead. If none of those files exists, the preference set is empty.
The preference file should contain a list of symbol–value lists written with the default parameter settings. Keys starting with racket:, mzscheme:, mred:, and plt: in any letter case are reserved for use by Racket implementors. If the preference file does not contain a list of symbol–value lists, an error is logged via log-errorand failure-thunk is called.
The result of get-preference is the value associated withname if it exists in the association list, or the result of calling failure-thunk otherwise.
Preference settings are cached (weakly) across calls toget-preference, using (path->complete-path filename)as a cache key. If flush-mode is provided as #f, the cache is used instead of re-consulting the preferences file. Ifflush-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.
On platforms for which preferences-lock-file-mode returns'file-lock and when use-lock? is true, preference-file reading is guarded by a lock; multiple readers can share the lock, but writers take the lock exclusively. If the preferences file cannot be read because the lock is unavailable,lock-there is called on the path of the lock file; iflock-there is #f, an exception is raised. The default lock-there handler retries about 5 times (with increasing delays between each attempt) before tryingtimeout-lock-there, and the default timeout-lock-theretriggers an exception.
See also put-preferences. For a more elaborate preference system, see preferences:get.
Old preferences files: When afilename is not provided and the file indicated by(find-system-path 'pref-file) does not exist, the following paths are checked for compatibility with old versions of Racket:
- Windows: (build-path (find-system-path 'pref-dir) 'up "PLT Scheme" "plt-prefs.ss")
- Mac OS: (build-path (find-system-path 'pref-dir) "org.plt-scheme.prefs.ss")
- Unix: (expand-user-path "~/.plt-scheme/plt-prefs.ss")
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, andvals 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., theprint-unreadable parameter is set to #f while writing preferences).
Current preference values are read from the preference file before updating, and a write 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; see preferences-lock-file-mode for more information. If the directory of the preferences file does not already exist, it is created.
If the write lock is already held, thenlocked-proc is called with a single argument: the path of the lock file. The default locked-proc (used when the locked-procargument is #f) 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 and locks are implemented by the presence of the lock file).
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.
Reports the way that the lock file is used to implement preference-file locking on the current platform.
The 'exists mode is currently used on all platforms except Windows. In 'exists mode, the existence of the lock file indicates that a write lock is held, and readers need no lock (because the preferences file is atomically updated viarename-file-or-directory).
The 'file-lock mode is currently used on Windows. In'file-lock mode, shared and exclusive locks (in the sense ofport-try-file-lock?) on the lock file reflect reader and writer locks on the preference-file content. (The preference file itself is not locked, because a lock would interfere with replacing the file via rename-file-or-directory.)
Creates a procedure suitable for use as the #:lock-thereargument to get-preference, where the name,failure-thunk, flush-mode, and filenameare all passed on to get-preference by the result procedure to retry the preferences lookup.
Before calling get-preference, the result procedure uses(sleep delay) to pause. Then, if (* 2 delay) is less than max-delay, the result procedure callsmake-handle-get-preference-locked to generate a new retry procedure to pass to get-preference, but with adelay of (* 2 delay). If (* 2 delay) is not less than max-delay, then get-preference is called with the given lock-there, instead.
Obtains a lock for the filename lock-file and then callsthunk. The filename argument specifies a file path prefix that is used only to generate the lock filename whenlock-file is #f. Specifically, whenlock-file is #f, thencall-with-file-lock/timeout uses make-lock-file-nameto build the lock filename. If the lock file does not yet exist, it is created; beware that the lock file is not deleted bycall-with-file-lock/timeout.
When thunk returns,call-with-file-lock/timeout releases the lock, returning the result ofthunk. The call-with-file-lock/timeout function will retry after delay seconds and continue retrying with exponential backoff until delay reaches max-delay. Ifcall-with-file-lock/timeout fails to obtain the lock,failure-thunk is called in tail position. The kind argument specifies whether the lock is 'shared or 'exclusivein the sense of port-try-file-lock?.
Examples:
File is locked Failed to obtain lock for file
Creates a lock filename by prepending "_LOCK" on Windows (i.e., when cross-system-type reports 'windows) or".LOCK" on other platforms to the file portion of the path.
Example:
> (make-lock-file-name "/home/george/project/important-file") #path:/home/george/project/.LOCKimportant-file
file-type-bits : #o170000 socket-type-bits : #o140000 symbolic-link-type-bits : #o120000 regular-file-type-bits : #o100000 block-device-type-bits : #o060000 directory-type-bits : #o040000 character-device-type-bits : #o020000 fifo-type-bits : #o010000 set-user-id-bit : #o004000 set-group-id-bit : #o002000 sticky-bit : #o001000 user-permission-bits : #o000700 user-read-bit : #o000400 user-write-bit : #o000200 user-execute-bit : #o000100 group-permission-bits : #o000070 group-read-bit : #o000040 group-write-bit : #o000020 group-execute-bit : #o000010 other-permission-bits : #o000007 other-read-bit : #o000004 other-write-bit : #o000002 other-execute-bit : #o000001