Common Lisp the Language, 2nd Edition

Next: Opening and Closing Up: File Names Previous: Discussion of Logical

## 23.1.6. Pathname Functions

These functions are what programs use to parse and default file names that have been typed in or otherwise supplied by the user.

Any argument called pathname in this book may actually be a pathname, a string or symbol, or a stream. Any argument called defaults may likewise be a pathname, a string or symbol, or a stream.

X3J13 voted in March 1988 (PATHNAME-SYMBOL) to change the language so that a symbol is never allowed as a pathname argument. More specifically, the following functions are changed to disallow a symbol as a pathname argument:

    pathname          pathname-device     namestring
    truename          pathname-directory  file-namestring
    parse-namestring  pathname-name       directory-namestring
    merge-pathnames   pathname-type       host-namestring
    pathname-host     pathname-version    enough-namestring

(The function `require` was also changed by this vote but was deleted from the language by a vote in January 1989 (REQUIRE-PATHNAME-DEFAULTS) .) Furthermore, the vote reaffirmed that the following functions do not accept symbols as file, filename, or pathname arguments:

    open             rename-file     file-write-date
    with-open-file   delete-file     file-author
    load             probe-file      directory
    compile-file

In older implementations of Lisp that did not have strings, for example MacLisp, symbols were the only means for specifying pathnames. This was convenient only because the file systems of the time allowed only uppercase letters in file names. Typing `(load 'foo)` caused the function `load` to receive the symbol `FOO` (with uppercase letters because of the way symbols are parsed) and therefore to load the file named `FOO`. Now that many file systems, most notably UNIX, support case-sensitive file names, the use of symbols is less convenient and more error-prone.

X3J13 voted in March 1988 (PATHNAME-STREAM) to specify that a stream may be used as a `pathname`, `file`, or `filename` argument only if it was created by use of `open` or `with-open-file`, or if it is a synonym stream whose symbol is bound to a stream that may be used as a pathname.

If such a stream is used as a pathname, it is as if the `pathname` function were applied to the stream and the resulting pathname used in place of the stream. This represents the name used to open the file. This may be, but is not required to be, the actual name of the file.

It is an error to attempt to obtain a pathname from a stream created by any of the following:

    make-two-way-stream              make-string-input-stream
    make-echo-stream                 make-string-output-stream
    make-broadcast-stream            with-input-from-string
    make-concatenated-stream         with-output-to-string

In the examples, it is assumed that the host named `CMUC` runs the TOPS-20 operating system, and therefore uses TOPS-20 file system syntax; furthermore, an explicit host name is indicated by following the host name with a double colon. Remember, however, that namestring syntax is implementation-dependent, and this syntax is used here purely for the sake of examples.

[Function]
`pathname pathname`

The `pathname` function converts its argument to be a pathname. The argument may be a pathname, a string or symbol, or a stream; the result is always a pathname.

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) .

X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that `pathname` is unaffected by whether its argument, if a stream, is open or closed. X3J13 further commented that because some implementations cannot provide the ``true name'' of a file until the file is closed, in such an implementation `pathname` might, in principle, return a different (perhaps more specific) file name after the stream is closed. However, such behavior is prohibited; `pathname` must return the same pathname after a stream is closed as it would have while the stream was open. See `truename`.

[Function]
`truename pathname`

The `truename` function endeavors to discover the ``true name'' of the file associated with the pathname within the file system. If the pathname is an open stream already associated with a file in the file system, that file is used. The ``true name'' is returned as a pathname. An error is signaled if an appropriate file cannot be located within the file system for the given pathname.

The `truename` function may be used to account for any file name translations performed by the file system, for example.

For example, suppose that `DOC:` is a TOPS-20 logical device name that is translated by the TOPS-20 file system to be `PS:<DOCUMENTATION>`.

    (setq file (open "CMUC::DOC:DUMPER.HLP"))
    (namestring (pathname file)) => "CMUC::DOC:DUMPER.HLP"
    (namestring (truename file))
       => "CMUC::PS:<DOCUMENTATION>DUMPER.HLP.13"

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) .

X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that `truename` may be applied to a stream whether the stream is open or closed. X3J13 further commented that because some implementations cannot provide the ``true name'' of a file until the file is closed, in principle it would be possible in such an implementation for `truename` to return a different file name after the stream is closed. Such behavior is permitted; in this respect `truename` differs from `pathname`.

X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that `truename` accepts only non-wild pathnames; an error is signaled if `wild-pathname-p` would be true of the pathname argument.

X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require `truename` to accept logical pathnames (see section 23.1.5). However, `truename` never returns a logical pathname.

[Function]
`parse-namestring thing &optional host defaults &key :start :end :junk-allowed`

This turns thing into a pathname. The thing is usually a string (that is, a namestring), but it may be a symbol (in which case the print name is used) or a pathname or stream (in which case no parsing is needed, but an error check may be made for matching hosts).

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) . The thing argument may not be a symbol.

X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require `parse-namestring` to accept logical pathname namestrings (see section 23.1.5).

This function does not, in general, do defaulting of pathname components, even though it has an argument named defaults; it only does parsing. The host and defaults arguments are present because in some implementations it may be that a namestring can only be parsed with reference to a particular file name syntax of several available in the implementation. If host is non-`nil`, it must be a host name that could appear in the host component of a pathname, or `nil`; if host is `nil` then the host name is extracted from the default pathname in defaults and used to determine the syntax convention. The defaults argument defaults to the value of `*default-pathname-defaults*`.

For a string (or symbol) argument, `parse-namestring` parses a file name within it in the range delimited by the `:start` and `:end` arguments (which are integer indices into string, defaulting to the beginning and end of the string).

See chapter 14 for a discussion of `:start` and `:end` arguments.

If `:junk-allowed` is not `nil`, then the first value returned is the pathname parsed, or `nil` if no syntactically correct pathname was seen.

If `:junk-allowed` is `nil` (the default), then the entire substring is scanned. The returned value is the pathname parsed. An error is signaled if the substring does not consist entirely of the representation of a pathname, possibly surrounded on either side by whitespace characters if that is appropriate to the cultural conventions of the implementation.

In either case, the second value is the index into the string of the delimiter that terminated the parse, or the index beyond the substring if the parse terminated at the end of the substring (as will always be the case if `:junk-allowed` is false).

If thing is not a string or symbol, then start (which defaults to zero in any case) is always returned as the second value.

Parsing an empty string always succeeds, producing a pathname with all components (except the host) equal to `nil`.

Note that if host is specified and not `nil`, and thing contains a manifest host name, an error is signaled if the hosts do not match.

If thing contains an explicit host name and no explicit device name, then it might be appropriate, depending on the implementation environment, for `parse-namestring` to supply the standard default device for that host as the device component of the resulting pathname.

[Function]
`merge-pathnames pathname &optional defaults default-version`

This is the function that most programs should call to process a file name supplied by the user. It fills in unspecified components of pathname from the defaults, and returns a new pathname. The pathname and defaults arguments may each be a pathname, stream, string, or symbol. The result is always a pathname.

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) .

X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require `merge-namestrings` to recognize a logical pathname namestring as its first argument if its second argument is a logical pathname (see section 23.1.5).

X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that `merge-pathname` is unaffected by whether the first argument, if a stream, is open or closed. If the first argument is a stream, `merge-pathname` behaves as if the function `pathname` were applied to the stream and the resulting pathname used instead.

X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to require `merge-pathnames` to map customary case in argument pathnames to the customary case in returned pathnames (see section 23.1.2).

defaults defaults to the value of `*default-pathname-defaults*`.

default-version defaults to `:newest`.

Here is an example of the use of `merge-pathnames`:

    (merge-pathnames "CMUC::FORMAT"
                     "CMUC::PS:<LISPIO>.FASL")
       => a pathname object that re-expressed as a namestring would be
          "CMUC::PS:<LISPIO>FORMAT.FASL.0"

Defaulting of pathname components is done by filling in components taken from another pathname. This is especially useful for cases such as a program that has an input file and an output file, and asks the user for the name of both, letting the unsupplied components of one name default from the other. Unspecified components of the output pathname will come from the input pathname, except that the type should default not to the type of the input but to the appropriate default type for output from this program.

The pathname merging operation takes as input a given pathname, a defaults pathname, and a default version, and returns a new pathname. Basically, the missing components in the given pathname are filled in from the defaults pathname, except that if no version is specified the default version is used. The default version is usually `:newest`; if no version is specified the newest version in existence should be used. The default version can be `nil`, to preserve the information that it was missing in the input pathname.

If the given pathname explicitly specifies a host and does not supply a device, then if the host component of the defaults matches the host component of the given pathname, then the device is taken from the defaults; otherwise the device will be the default file device for that host. Next, if the given pathname does not specify a host, device, directory, name, or type, each such component is copied from the defaults. The merging rules for the version are more complicated and depend on whether the pathname specifies a name. If the pathname doesn't specify a name, then the version, if not provided, will come from the defaults, just like the other components. However, if the pathname does specify a name, then the version is not affected by the defaults. The reason is that the version ``belongs to'' some other file name and is unlikely to have anything to do with the new one. Finally, if this process leaves the version missing, the default version is used.

The net effect is that if the user supplies just a name, then the host, device, directory, and type will come from the defaults, but the version will come from the default version argument to the merging operation. If the user supplies nothing, or just a directory, the name, type, and version will come over from the defaults together. If the host's file name syntax provides a way to input a version without a name or type, the user can let the name and type default but supply a version different from the one in the defaults.

X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree: `merge-pathname` might or might not perform plausibility checking on its arguments to ensure that the resulting pathname can be converted a valid namestring. User beware: this could cause portability problems.

For example, suppose that host `LOSER` constrains file types to be three characters or fewer but host `CMUC` does not. Then `"LOSER::FORMAT"` is a valid namestring and `"CMUC::PS:<LISPIO>.FASL"` is a valid namestring, but

    (merge-pathnames "LOSER::FORMAT" "CMUC::PS:<LISPIO>.FASL")

might signal an error in some implementations because the hypothetical result would be a pathname equivalent to the namestring `"LOSER::FORMAT.FASL"` which is illegal because the file type `FASL` has more than three characters. In other implementations `merge-pathname` might return a pathname but that pathname might cause `namestring` to signal an error.

[Variable]
`*default-pathname-defaults*`

This is the default pathname-defaults pathname; if any pathname primitive that needs a set of defaults is not given one, it uses this one. As a general rule, however, each program should have its own pathname defaults rather than using this one.

[Function]
`make-pathname &key :host :device :directory :name :type :version :defaults`

Given some components, `make-pathname` constructs and returns a pathname. After the components specified explicitly by the `:host`, `:device`, `:directory`, `:name`, `:type`, and `:version` arguments are filled in, the merging rules used by `merge-pathnames` are used to fill in any missing components from the defaults specified by the `:defaults` argument. The default value of the `:defaults` argument is a pathname whose host component is the same as the host component of the value of `*default-pathname-defaults*`, and whose other components are all `nil`.

Whenever a pathname is constructed, whether by `make-pathname` or some other function, the components may be canonicalized if appropriate. For example, if a file system is insensitive to case, then alphabetic characters may be forced to be all uppercase or all lowercase by the implementation.

The following example assumes the use of UNIX syntax and conventions.

    (make-pathname :host "technodrome"
                   :directory '(:absolute "usr" "krang")
                   :name "shredder")
      => #P"technodrome:/usr/krang/shredder"

X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to add a new keyword argument `:case` to `make-pathname`. The new argument description is therefore as follows:

[Function]
`make-pathname &key :host :device :directory :name :type :version :defaults :case`

See section 23.1.2 for a description of the `:case` argument.

X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree: `make-pathname` might or might not check on its arguments to ensure that the resulting pathname can be converted to a valid namestring. If `make-pathname` does not check its arguments and signal an error in problematical cases, `namestring` yet might or might not signal an error when given the resulting pathname. User beware: this could cause portability problems.

[Function]
`pathnamep object`

This predicate is true if object is a pathname, and otherwise is false.

    (pathnamep x) == (typep x 'pathname)

[Function]
`pathname-host pathname
``pathname-device pathname
``pathname-directory pathname
``pathname-name pathname
``pathname-type pathname
``pathname-version pathname`

These return the components of the argument pathname, which may be a pathname, string or symbol, or stream. The returned values can be strings, special symbols, or some other object in the case of structured components. The type will always be a string or a symbol. The version will always be a number or a symbol.

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) .

X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that these operations are unaffected by whether the first argument, if a stream, is open or closed. If the first argument is a stream, each operation behaves as if the function `pathname` were applied to the stream and the resulting pathname used instead.

X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to add a keyword argument `:case` to all of the pathname accessor functions except `pathname-version`. The new argument descriptions are therefore as follows:

[Function]
`pathname-host pathname &key :case
``pathname-device pathname &key :case
``pathname-directory pathname &key :case
``pathname-name pathname &key :case
``pathname-type pathname &key :case
``pathname-version pathname`

See section 23.1.2 for a description of the `:case` argument.

X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to specify that `pathname-directory` always returns `nil`, `:unspecific`, or a list-never a string, never `:wild` (see section 23.1.3). If a list is returned, it is not guaranteed to be freshly consed; the consequences of modifying this list are undefined.

[Function]
`namestring pathname
``file-namestring pathname
``directory-namestring pathname
``host-namestring pathname
``enough-namestring pathname &optional defaults`

The pathname argument may be a pathname, a string or symbol, or a stream that is or was open to a file. The name represented by pathname is returned as a namelist in canonical form.

If pathname is a stream, the name returned represents the name used to open the file, which may not be the actual name of the file (see `truename`).

X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL) and to specify exactly which streams may be used as pathnames (PATHNAME-STREAM) .

X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that these operations are unaffected by whether the first argument, if a stream, is open or closed. If the first argument is a stream, each operation behaves as if the function `pathname` were applied to the stream and the resulting pathname used instead.

`namestring` returns the full form of the pathname as a string. `file-namestring` returns a string representing just the name, type, and version components of the pathname; the result of `directory-namestring` represents just the directory-name portion; and `host-namestring` returns a string for just the host-name portion. Note that a valid namestring cannot necessarily be constructed simply by concatenating some of the three shorter strings in some order.

`enough-namestring` takes another argument, defaults. It returns an abbreviated namestring that is just sufficient to identify the file named by pathname when considered relative to the defaults (which defaults to the value of `*default-pathname-defaults*`). That is, it is required that

    (merge-pathnames (enough-namestring pathname defaults) defaults) ==
     (merge-pathnames (parse-namestring pathname nil defaults) defaults)

in all cases; and the result of `enough-namestring` is, roughly speaking, the shortest reasonable string that will still satisfy this criterion.

X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree: `make-pathname` and `merge-pathnames` might or might not be able to produce pathnames that cannot be converted to valid namestrings. User beware: this could cause portability problems.

[Function]
`user-homedir-pathname &optional host`

Returns a pathname for the user's ``home directory'' on host. The host argument defaults in some appropriate implementation-dependent manner. The concept of ``home directory'' is itself somewhat implementation-dependent, but from the point of view of Common Lisp it is the directory where the user keeps personal files such as initialization files and mail. If it is impossible to determine this information, then `nil` is returned instead of a pathname; however, `user-homedir-pathname` never returns `nil` if the host argument is not specified. This function returns a pathname without any name, type, or version component (those components are all `nil`).

Next: Opening and Closing Up: File Names Previous: Discussion of Logical