15.1.1 Manipulating Paths

► |  | The Racket Reference

1 | Language Model
2 | Notation for Documentation
3 | Syntactic Forms
4 | Datatypes
5 | Structures
6 | Classes and Objects
7 | Units
8 | Contracts
9 | Pattern Matching
10 | Control Flow
11 | Concurrency and Parallelism
12 | Macros
13 | Input and Output
14 | Reflection and Security
15 | Operating System
16 | Memory Management
17 | Unsafe Operations
18 | Running Racket
| Bibliography
| Index

► | 15 | Operating System

15.1 | Paths
15.2 | Filesystem
15.3 | Networking
15.4 | Processes
15.5 | Logging
15.6 | Time
15.7 | Environment Variables
15.8 | Environment and Runtime Information
15.9 | Command-Line Parsing
15.10 | Additional Operating System Functions

▼ | 15.1 | Paths

15.1.1 | Manipulating Paths
15.1.2 | More Path Utilities
15.1.3 | Unix and Mac OS Paths
15.1.4 | Windows Paths

On this page:

path?
path-string?
path-for-some-system?
string->path
bytes->path
path->string
path->bytes
string->path-element
bytes->path-element
path-element->string
path-element->bytes
path<?
path-convention-type
system-path-convention-type
build-path
build-path/ convention-type
absolute-path?
relative-path?
complete-path?
path->complete-path
path->directory-path
resolve-path
cleanse-path
expand-user-path
simplify-path
normal-case-path
split-path
explode-path
path-replace-extension
path-add-extension
path-replace-suffix
path-add-suffix
reroot-path

top contents ← prev up next →

##### 15.1.1`` Manipulating Paths🔗ℹ

> procedure (path? v) → boolean?
> v : any/c

Returns #t if v is a path value for the current platform (not a string, and not a path for a different platform), #f otherwise.

> procedure (path-string? v) → boolean?
> v : any/c

Returns #t if v is either a path or string: either a path for the current platform or a non-empty string without nul characters. Returns #f otherwise.

> procedure (path-for-some-system? v) → boolean?
> v : any/c

Returns #t if v is a path value for some platform (not a string), #f otherwise.

> procedure (string->path str) → path?
> str : string?

Produces a path whose byte-string encoding is (string->bytes/locale str (char->integer #\?)) on Unix and Mac OS or (string->bytes/utf-8 str) on Windows.

Beware that the current locale might not encode every string, in which case string->path can produce the same path for different strs. See also string->path-element, which should be used instead of string->path when a string represents a single path element. For information on how strings and byte strings encode paths, see Unix Path Representation and Windows Path Representation.

See also string->some-system-path, and see Unix Path Representation and Windows Path Representation for information on how strings encode paths.

Changed in version 6.1.1.1 of package base: Changed Windows conversion to always use UTF-8.

> procedure (bytes->path bstr [type]) → path?
> bstr : bytes?
> type : (or/c 'unix 'windows) = (system-path-convention-type)

Produces a path (for some platform) whose byte-string encoding is bstr, where bstr must not contain a nul byte. The optional type specifies the convention to use for the path.

For converting relative path elements from literals, use instead bytes->path-element, which applies a suitable encoding for individual elements.

For information on how byte strings encode paths, see Unix Path Representation and Windows Path Representation.

> procedure (path->string path) → string?
> path : path?

Produces a string that represents path by decoding path’s byte-string encoding using the current locale on Unix and Mac OS and by using UTF-8 on Windows. In the former case, ? is used in the result string where encoding fails, and if the encoding result is the empty string, then the result is "?".

The resulting string is suitable for displaying to a user, string-ordering comparisons, etc., but it is not suitable for re-creating a path (possibly modified) via string->path, since decoding and re-encoding the path’s byte string may lose information.

Furthermore, for display and sorting based on individual path elements (such as pathless file names), use path-element->string, instead, to avoid special encodings use to represent some relative paths. See Windows Paths for specific information about the conversion of Windows paths.

See also some-system-path->string.

Changed in version 6.1.1.1 of package base: Changed Windows conversion to always use UTF-8.

> procedure (path->bytes path) → bytes?
> path : path-for-some-system?

Produces path’s byte-string representation. No information is lost in this translation, so that (bytes->path (path->bytes path) (path-convention-type path)) always produces a path that is equal? to path. The path argument can be a path for any platform.

Conversion to and from byte values is useful for marshaling and unmarshaling paths, but manipulating the byte form of a path is generally a mistake. In particular, the byte string may start with a \\?\REL encoding for Windows paths. Instead of path->bytes, use split-path and path-element->bytes to manipulate individual path elements.

For information on how byte strings encode paths, see Unix Path Representation and Windows Path Representation.

> > procedure
> > (string->path-element |  | str |
> > | [ | false-on-non-element?]) |
> → (or/c (and/c path? path-element?) #f)
> str : string?
> false-on-non-element? : any/c = #f

Like string->path, except that str corresponds to a single relative element in a path, and it is encoded as necessary to convert it to a path. See Unix and Mac OS Paths and Windows Paths for more information on the conversion of paths.

If str does not correspond to any path element (e.g., it is an absolute path, or it can be split), or if it corresponds to an up-directory or same-directory indicator on Unix and Mac OS, then either #f is returned or exn:fail:contract exception is raised. A #f is returned only when false-on-non-element? is true.

Like path->string, information can be lost from str in the locale-specific conversion to a path.

Changed in version 8.1.0.6 of package base: Added the false-on-non-element? argument.

> > procedure
> > (bytes->path-element |  | bstr |
> > | [ | type |
> > |  | false-on-non-element?]) |
> → (or/c path-element? #f)
> bstr : bytes?
> type : (or/c 'unix 'windows) = (system-path-convention-type)
> false-on-non-element? : any/c = #f

Like bytes->path, except that bstr corresponds to a single relative element in a path. In terms of conversions, restrictions on bstr, and the treatment of false-on-non-element?, bytes->path-element is like string->path-element.

The bytes->path-element procedure is generally the best choice for reconstructing a path based on another path (where the other path is deconstructed with split-path and path-element->bytes) when ASCII-level manipulation of path elements is necessary.

Changed in version 8.1.0.6 of package base: Added the false-on-non-element? argument.

> procedure (path-element->string path) → string?
> path : path-element?

Like path->string, except that trailing path separators are removed (as by split-path). On Windows, any \\?\REL encoding prefix is also removed; see Windows Paths for more information.

The path argument must be such that split-path applied to path would return 'relative as its first result and a path as its second result, otherwise the exn:fail:contract exception is raised.

The path-element->string procedure is generally the best choice for presenting a pathless file or directory name to a user.

> procedure (path-element->bytes path) → bytes?
> path : path-element?

Like path->bytes, except that any encoding prefix is removed, etc., as for path-element->string.

For any reasonable locale, consecutive ASCII characters in the printed form of path are mapped to consecutive byte values that match each character’s code-point value, and a leading or trailing ASCII character is mapped to a leading or trailing byte, respectively. The path argument can be a path for any platform.

The path-element->bytes procedure is generally the right choice (in combination with split-path) for extracting the content of a path to manipulate it at the ASCII level (then reassembling the result with bytes->path-element and build-path).

> procedure (path<? a-path b-path ...) → boolean?
> a-path : path?
> b-path : path?

Returns #t if the arguments are sorted, where the comparison for each pair of paths is the same as using path->bytes and bytes<?.

Changed in version 7.0.0.13 of package base: Allow one argument, in addition to allowing two or more.

> procedure (path-convention-type path) → (or/c 'unix 'windows)
> path : path-for-some-system?

Accepts a path value (not a string) and returns its convention type.

> procedure (system-path-convention-type) → (or/c 'unix 'windows)

Returns the path convention type of the current platform: 'unix for Unix and Mac OS, 'windows for Windows.

> procedure (build-path base sub ...) → path-for-some-system?
> base : (or/c path-string? path-for-some-system? 'up 'same)
> | sub |  | : |  |
> (or/c (and/c (or/c path-string? path-for-some-system?)
> (not/c complete-path?))
> (or/c 'up 'same))

Creates a path given a base path and any number of sub-path extensions. If base is an absolute path, the result is an absolute path, otherwise the result is a relative path.

The base and each sub must be either a relative path, the symbol 'up (indicating the relative parent directory), or the symbol 'same (indicating the relative current directory). For Windows paths, if base is a drive specification (with or without a trailing slash) the first sub can be an absolute (driveless) path. For all platforms, the last sub can be a filename.

The base and sub arguments can be paths for any platform. The platform for the resulting path is inferred from the base and sub arguments, where string arguments imply a path for the current platform. If different arguments are for different platforms, the exn:fail:contract exception is raised. If no argument implies a platform (i.e., all are 'up or 'same), the generated path is for the current platform.

Each sub and base can optionally end in a directory separator. If the last sub ends in a separator, it is included in the resulting path.

If base or sub is an illegal path string (because it is empty or contains a nul character), the exn:fail:contract exception is raised.

The build-path procedure builds a path without checking the validity of the path or accessing the filesystem.

See Unix and Mac OS Paths and Windows Paths for more information on the construction of paths.

The following examples assume that the current directory is "/home/joeuser" for Unix examples and "C:\Joe’s Files" for Windows examples.

> (define p1 (build-path (current-directory) "src" "racket"))
> ; Unix: p1 is "/home/joeuser/src/racket"
> ; Windows: p1 is "C:\\Joe's Files\\src\\racket"
> (define p2 (build-path 'up 'up "docs" "Racket"))
> ; Unix: p2 is "../../docs/Racket"
> ; Windows: p2 is "..\\..\\docs\\Racket"
> (build-path p2 p1)
> ; Unix and Windows: raises exn:fail:contract; p1 is absolute
> (build-path p1 p2)
> ; Unix: is "/home/joeuser/src/racket/../../docs/Racket"
> ; Windows: is "C:\\Joe's Files\\src\\racket\\..\\..\\docs\\Racket"

> > procedure
> > (build-path/convention-type |  | type |  |  |  |
> > |  | base |  |  |  |
> > |  | sub ...) |  | → |  | path-for-some-system?
> type : (or/c 'unix 'windows)
> base : (or/c path-string? path-for-some-system? 'up 'same)
> | sub |  | : |  |
> (or/c (and/c (or/c path-string? path-for-some-system?)
> (not/c complete-path?))
> (or/c 'up 'same))

Like build-path, except a path convention type is specified explicitly.

Note that, just as with build-path, any string arguments for either base or sub will be implicitly converted into a path for the current platform before being combined with the others. For this reason, you cannot use this function to build paths from strings for any platform other than the current one; in such attempts, type does not match the inferred convention type for the strings and an exn:fail:contract exception is raised. (To create paths for foreign platforms, see bytes->path.)

The usefulness of build-path/convention-type over build-path is limited to cases where the sub-paths contain 'same or 'up elements.

> procedure (absolute-path? path) → boolean?
> path : (or/c path? string? path-for-some-system?)

Returns #t if path is an absolute path, #f otherwise. The path argument can be a path for any platform. If path is not a legal path string (e.g., it contains a nul character), #f is returned. This procedure does not access the filesystem.

> procedure (relative-path? path) → boolean?
> path : (or/c path? string? path-for-some-system?)

Returns #t if path is a relative path, #f otherwise. The path argument can be a path for any platform. If path is not a legal path string (e.g., it contains a nul character), #f is returned. This procedure does not access the filesystem.

> procedure (complete-path? path) → boolean?
> path : (or/c path? string? path-for-some-system?)

Returns #t if path is a completely determined path (not relative to a directory or drive), #f otherwise. The path argument can be a path for any platform. Note that for Windows paths, an absolute path can omit the drive specification, in which case the path is neither relative nor complete. If path is not a legal path string (e.g., it contains a nul character), #f is returned.

This procedure does not access the filesystem.

> procedure (path->complete-path path [base]) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> | base |  | : |  | (or/c path-string? path-for-some-system?)
> |  |  | = |  | (current-directory)

Returns path as a complete path. If path is already a complete path, it is returned as the result. Otherwise, path is resolved with respect to the complete path base. If base is not a complete path, the exn:fail:contract exception is raised.

The path and base arguments can be paths for any platform; if they are for different platforms, the exn:fail:contract exception is raised.

This procedure does not access the filesystem.

> procedure (path->directory-path path) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)

Returns path if path syntactically refers to a directory and ends in a separator, otherwise it returns an extended version of path that specifies a directory and ends with a separator. For example, on Unix and Mac OS, the path "x/y/" syntactically refers to a directory and ends in a separator, but "x/y" would be extended to "x/y/", and "x/.." would be extended to "x/../". The path argument can be a path for any platform, and the result will be for the same platform.

This procedure does not access the filesystem.

> procedure (resolve-path path) → path?
> path : path-string?

Cleanses path and returns a path that references the same file or directory as path. If path is a soft link to another path, then the referenced path is returned (this may be a relative path with respect to the directory owning path), otherwise path is returned (after cleansing).

On Windows, the path for a link should be simplified syntactically, so that an up-directory indicator removes a preceding path element independent of whether the preceding element itself refers to a link. For relative-paths links, the path should be parsed specially; see Windows Paths for more information.

Changed in version 6.0.1.12 of package base: Added support for links on Windows.

> procedure (cleanse-path path) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)

Cleanses path (as described at the beginning of this chapter) without consulting the filesystem.

Example:

> > (let ([p (string->some-system-path "tiny//dancer" 'unix)])
> (cleanse-path p))
> #<path:tiny/dancer>

> procedure (expand-user-path path) → path?
> path : path-string?

Cleanses path. In addition, on Unix and Mac OS, a leading ~ is treated as user’s home directory and expanded; the username follows the ~ (before a / or the end of the path), where ~ by itself indicates the home directory of the current user.

> procedure (simplify-path path [use-filesystem?]) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> use-filesystem? : boolean? = #t

Eliminates redundant path separators (except for a single trailing separator), up-directory .., and same-directory . indicators in path, and changes / separators to \ separators in Windows paths, such that the result accesses the same file or directory (if it exists) as path.

In general, the pathname is normalized as much as possible—without consulting the filesystem if use-filesystem? is #f, and (on Windows) without changing the case of letters within the path. If path syntactically refers to a directory, the result ends with a directory separator.

When path is simplified other than just converting slashes to backslashes and use-filesystem? is true (the default), a complete path is returned. If path is relative, it is resolved with respect to the current directory. On Unix and Mac OS, up-directory indicators are removed taking into account soft links (so that the resulting path refers to the same directory as before); on Windows, up-directory indicators are removed by deleting a preceding path element.

When use-filesystem? is #f, up-directory indicators are removed by deleting a preceding path element, and the result can be a relative path with up-directory indicators remaining at the beginning of the path; up-directory indicators are dropped when they refer to the parent of a root directory. Similarly, the result can be the same as (build-path 'same) (but with a trailing separator) if eliminating up-directory indicators leaves only same-directory indicators.

The path argument can be a path for any platform when use-filesystem? is #f, and the resulting path is for the same platform.

The filesystem might be accessed when use-filesystem? is true, but the source or simplified path might be a non-existent path. If path cannot be simplified due to a cycle of links, the exn:fail:filesystem exception is raised (but a successfully simplified path may still involve a cycle of links if the cycle did not inhibit the simplification).

See Unix and Mac OS Paths and Windows Paths for more information on simplifying paths.

Example:

> > (let ([p (string->some-system-path "tiny//in/my/head/../../../dancer" 'unix)])
> (simplify-path p #f))
> #<path:tiny/dancer>

> procedure (normal-case-path path) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)

Returns path with “normalized” case characters. For Unix and Mac OS paths, this procedure always returns the input path, because filesystems for these platforms can be case-sensitive. For Windows paths, if path does not start with \\?\, the resulting string uses only lowercase letters, based on the current locale. In addition, for Windows paths when the path does not start with \\?\, all /s are converted to \s, and trailing spaces and .s are removed.

The path argument can be a path for any platform, but beware that local-sensitive decoding and conversion of the path may be different on the current platform than for the path’s platform.

This procedure does not access the filesystem.

> > procedure
> > (split-path path) |  | → |  |
> > (or/c path-for-some-system? 'relative #f)
> > (or/c path-for-some-system? 'up 'same)
> > boolean?
> path : (or/c path-string? path-for-some-system?)

Deconstructs path into a smaller path and an immediate directory or file name. Three values are returned:

- base is either

  - a path,

  - 'relative if path is an immediate relative directory or filename, or

  - #f if path is a root directory.

- name is either

  - a directory-name path,

  - a filename,

  - 'up if the last part of path specifies the parent directory of the preceding path (e.g., .. on Unix), or

  - 'same if the last part of path specifies the same directory as the preceding path (e.g., . on Unix).

- must-be-dir? is #t if path explicitly specifies a directory (e.g., with a trailing separator), #f otherwise. Note that must-be-dir? does not specify whether name is actually a directory or not, but whether path syntactically specifies a directory.

Compared to path, redundant separators (if any) are removed in the result base and name. If base is #f, then name cannot be 'up or 'same. The path argument can be a path for any platform, and resulting paths for the same platform.

This procedure does not access the filesystem.

See Unix and Mac OS Paths and Windows Paths for more information on splitting paths.

> procedure (explode-path path)
> → (listof (or/c path-for-some-system? 'up 'same))
> path : (or/c path-string? path-for-some-system?)

Returns the list of path elements that constitute path. If path is simplified in the sense of simple-form-path, then the result is always a list of paths, and the first element of the list is a root.

The explode-path function computes its result in time proportional to the length of path (unlike a loop in that uses split-path, which must allocate intermediate paths).

> procedure (path-replace-extension path ext) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> ext : (or/c string? bytes?)

Returns a path that is the same as path, except that the extension for the last element of the path (including the extension separator) is changed to ext. If the last element of path has no extension, then ext is added to the path.

An extension is defined as a . that is not at the start of the path element followed by any number of non-. characters/bytes at the end of the path element, as long as the path element is not a directory indicator like "..".

The path argument can be a path for any platform, and the result is for the same platform. If path represents a root, the exn:fail:contract exception is raised. The given ext typically starts with ., but it is not required to start with an extension separator.

Examples:

> > (path-replace-extension "x/y.ss" #".rkt")
> #<path:x/y.rkt>
> > (path-replace-extension "x/y.ss" #"")
> #<path:x/y>
> > (path-replace-extension "x/y" #".rkt")
> #<path:x/y.rkt>
> > (path-replace-extension "x/y.tar.gz" #".rkt")
> #<path:x/y.tar.rkt>
> > (path-replace-extension "x/.racketrc" #".rkt")
> #<path:x/.racketrc.rkt>

Added in version 6.5.0.3 of package base.

> procedure (path-add-extension path ext [sep]) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> ext : (or/c string? bytes?)
> sep : (or/c string? bytes?) = #"_"

Similar to path-replace-extension, but any existing extension on path is preserved by replacing the . before the extension with sep, and then the ext is added to the end.

Examples:

> > (path-add-extension "x/y.ss" #".rkt")
> #<path:x/y_ss.rkt>
> > (path-add-extension "x/y" #".rkt")
> #<path:x/y.rkt>
> > (path-add-extension "x/y.tar.gz" #".rkt")
> #<path:x/y.tar_gz.rkt>
> > (path-add-extension "x/y.tar.gz" #".rkt" #".")
> #<path:x/y.tar.gz.rkt>
> > (path-add-extension "x/.racketrc" #".rkt")
> #<path:x/.racketrc.rkt>

Added in version 6.5.0.3 of package base.
Changed in version 6.8.0.2: Added the sep optional argument.

> procedure (path-replace-suffix path ext) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> ext : (or/c string? bytes?)

> NOTE: This function is deprecated; use path-replace-extension, instead.

Like path-replace-extension, but treats a leading . in a path element as an extension separator.

> procedure (path-add-suffix path ext) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> ext : (or/c string? bytes?)

> NOTE: This function is deprecated; use path-add-extension, instead.

Like path-add-extension, but treats a leading . in a path element as an extension separator.

> procedure (reroot-path path root-path) → path-for-some-system?
> path : (or/c path-string? path-for-some-system?)
> root-path : (or/c path-string? path-for-some-system?)

Produces a path that extends root-path based on the complete form of path.

If path is not already complete, is it completed via path->complete-path, in which case path must be a path for the current platform. The path argument is also cleansed and case-normalized via normal-case-path. The path is then appended to root-path; in the case of Windows paths, a root letter drive becomes a letter path element, while a root UNC path is prefixed with "UNC" as a path element and the machine and volume names become path elements.

Examples:

> > (reroot-path (bytes->path #"/home/caprica/baltar" 'unix)
> (bytes->path #"/earth" 'unix))
> #<path:/earth/home/caprica/baltar>
> > (reroot-path (bytes->path #"c:\\usr\\adama" 'windows)
> (bytes->path #"\\\\earth\\africa\\" 'windows))
> #<windows-path:\\earth\africa\c\usr\adama>
> > (reroot-path (bytes->path #"\\\\galactica\\cac\\adama" 'windows)
> (bytes->path #"s:\\earth\\africa\\" 'windows))
> #<windows-path:s:\earth\africa\UNC\galactica\cac\adama>

top contents ← prev up next →