Common Lisp the Language, 2nd Edition

Next: Extended Wildcards Up: File Names Previous: Case Conventions

## 23.1.3. Structured Directories

X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to define a specific pathname component format for structured directories.

The value of a pathname's directory component may be a list. The car of the list should be a keyword, either `:absolute` or `:relative`. Each remaining element of the list should be a string or a symbol (see below). Each string names a single level of directory structure and should consist of only the directory name without any punctuation characters.

A list whose car is the symbol `:absolute` represents a directory path starting from the root directory. For example, the list `(:absolute)` represents the root directory itself; the list `(:absolute "foo" "bar" "baz")` represents the directory that in a UNIX file system would be called `/foo/bar/baz`.

A list whose car is the symbol `:relative` represents a directory path starting from a default directory. The list `(:relative)` has the same meaning as `nil` and hence normally is not used. The list `(:relative "foo" "bar")` represents the directory named `bar` in the directory named `foo` in the default directory.

In place of a string, at any point in the list, a symbol may occur to indicate a special file notation. The following symbols have standard meanings.

`:wild`
  Wildcard match of one level of directory structure
`:wild-inferiors`
  Wildcard match of any number of directory levels
`:up`
  Go upward in directory structure (semantic)
`:back`
  Go upward in directory structure (syntactic)

(See section 23.1.4 for a discussion of wildcard pathnames.)

Implementations are permitted to add additional objects of any non-string type if necessary to represent features of their file systems that cannot be represented with the standard strings and symbols. Supplying any non-string, including any of the symbols listed below, to a file system for which it does not make sense signals an error of type `file-error`. For example, most implementations of the UNIX file system do not support `:wild-inferiors`. Any directory list in which `:absolute` or `:wild-inferiors` is immediately followed by `:up` or `:back` is illegal and when processed causes an error to be signaled.

The keyword `:back` has a ``syntactic'' meaning that depends only on the pathname and not on the contents of the file system. The keyword `:up` has a ``semantic'' meaning that depends on the contents of the file system; to resolve a pathname containing `:up` to a pathname whose directory component contains only `:absolute` and strings requires a search of the file system. Note that use of `:up` instead of `:back` can result in designating a different actual directory only in file systems that support multiple names for directories, perhaps via symbolic links. For example, suppose that there is a directory link such that

    (:absolute "X" "Y")  is linked to  (:absolute "A" "B")

and there also exist directories

    (:absolute "A" "Q")  and  (:absolute "X" "Q")

Then

    (:absolute "X" "Y" :up "Q")  designates  (:absolute "A" "Q")

but

    (:absolute "X" "Y" :back "Q")  designates  (:absolute "X" "Q")

If a string is used as the value of the `:directory` argument to `make-pathname`, it should be the name of a top-level directory and should not contain any punctuation characters. Specifying a string s is equivalent to specifying the list `(:absolute s)`. Specifying the symbol `:wild` is equivalent to specifying the list `(:absolute :wild-inferiors)` (or `(:absolute :wild)` in a file system that does not support `:wild-inferiors`).

The function `pathname-directory` always returns `nil`, `:unspecific`, or a list-never a string, never `:wild`. If a list is returned, it is not guaranteed to be freshly consed; the consequences of modifying this list are undefined.

In non-hierarchical file systems, the only valid list values for the directory component of a pathname are `(:absolute s)` (where s is a string) and `(:absolute :wild)`. The keywords `:relative`, `:wild-inferiors`, `:up`, and `:back` are not used in non-hierarchical file systems.

Pathname merging treats a relative directory specially. Let pathname and defaults be the first two arguments to `merge-pathnames`. If `(pathname-directory pathname)` is a list whose car is `:relative`, and `(pathname-directory defaults)` is a list, then the merged directory is the value of

    (append (pathname-directory defaults)
            (cdr     ;Remove :relative from the front
              (pathname-directory pathname)))

except that if the resulting list contains a string or `:wild` immediately followed by `:back`, both of them are removed. This removal of redundant occurrences of `:back` is repeated as many times as possible. If `(pathname-directory defaults)` is not a list or `(pathname-directory pathname)` is not a list whose car is `:relative`, the merged directory is the value of

    (or (pathname-directory pathname)
        (pathname-directory defaults))

A relative directory in the pathname argument to a function such as `open` is merged with the value of `*default-pathname-defaults*` before the file system is accessed.

Here are some examples of the use of structured directories. Suppose that host `L` supports a Symbolics Lisp Machine file system, host `U` supports a UNIX file system, and host `V` supports a VAX/VMS file system.

    (pathname-directory (parse-namestring "V:[FOO.BAR]BAZ.LSP"))
       => (:ABSOLUTE "FOO" "BAR")

    (pathname-directory (parse-namestring "U:/foo/bar/baz.lisp"))
       => (:ABSOLUTE "foo" "bar")

    (pathname-directory (parse-namestring "U:../baz.lisp"))
       => (:RELATIVE :UP)

    (pathname-directory (parse-namestring "U:/foo/bar/../mum/baz"))
       => (:ABSOLUTE "foo" "bar" :UP "mum")

    (pathname-directory (parse-namestring "U:bar/../../ztesch/zip"))
       => (:RELATIVE "bar" :UP :UP "ztesch")

    (pathname-directory (parse-namestring "L:>foo>**>bar>baz.lisp"))
       => (:ABSOLUTE "FOO" :WILD-INFERIORS "BAR")

    (pathname-directory (parse-namestring "L:>foo>*>bar>baz.lisp"))
       => (:ABSOLUTE "FOO" :WILD "BAR")

Next: Extended Wildcards Up: File Names Previous: Case Conventions