Some
file systems provide more complex conventions for wildcards than
simple component-wise wildcards representable by :wild.
For example, the namestring "F*O" might mean a normal three-character
name; a three-character name with the middle character wild;
a name with at least two characters, beginning with F and ending with O;
or perhaps a wild match spanning multiple directories. Similarly, the
namestring ">foo>**>bar>" might imply that the middle directory is
named "**"; the middle directory is :wild;
there are zero or more middle directories that are :wild;
or perhaps that the middle directory name matches any two-letter name.
Some file systems support even more complex wildcards, such as
regular expressions.

X3J13 voted in June 1989 (PATHNAME-WILD) to provide
some facilities for dealing with more general wildcard pathnames
in a fairly portable manner.

[Function]wild-pathname-p pathname &optional field-key

Tests a pathname for the presence of wildcard components. If the
first argument is not a pathname, string, or file
stream, an error of type type-error is
signaled.

If no field-key is provided, or the field-key is
nil, the result is true if and only
if pathname has any wildcard components.

If a non-null field-key is provided, it must be one of :host,
:device,
:directory, :name, :type, or :version.
In this case, the result is true if and only
if the indicated component of pathname is a wildcard.

Note that X3J13 voted in June 1989
(PATHNAME-COMPONENT-VALUE)
to specify that an implementation need not support wildcards in all fields;
the only requirement is that the name, type, or version may be :wild.
However, portable programs should be prepared to encounter either :wild
or implementation-dependent wildcards in any pathname component.
The function wild-pathname-p provides a portable way for testing
the presence of wildcards.

[Function]pathname-match-p pathnamewildname

This predicate is true if and only if the pathname
matches the wildname. The matching rules
are implementation-defined but should be consistent with the behavior of the
directory function. Missing components of wildname default to :wild.

If either argument is not a pathname, string, or file stream, an error
of type type-error is signaled. It is valid for pathname to be a
wild pathname; a wildcard field in pathname will match only a
wildcard field in wildname; that is, pathname-match-p is not commutative.
It is valid for wildname to be a non-wild pathname;
I believe that in this case pathname-match-p will have the same
behavior as equal, though the X3J13 specification did not say so.

[Function]translate-pathname sourcefrom-wildnameto-wildname &key

Translates the pathname source, which must match from-wildname, into
a corresponding pathname (call it result), which is constructed
so as to match to-wildname, and returns result.

The pathname result is a copy of
to-wildname with each missing or wildcard
field replaced by a portion of source; for this purpose a wildcard field is a
pathname component with a value of :wild, a :wild element of a
list-valued directory component, or an implementation-defined portion
of a component, such as the * in the complex wildcard string
"foo*bar" that some implementations support. An implementation that
adds other wildcard features, such as regular expressions, must define
how translate-pathname extends to those features. A missing field is
a pathname component that is nil.

The portion of source that is copied into result is
implementation-defined. Typically it is determined by the user interface conventions
of the file systems involved. Usually it is the portion of source
that matches a wildcard field of from-wildname that is in the same
position as the missing or wildcard field of to-wildname. If there
is no wildcard field in from-wildname at that position, then usually
it is the entire corresponding pathname component of source or, in
the case of a list-valued directory component, the entire corresponding
list element. For example, if the name components of source,
from-wildname, and to-wildname are "gazonk", "gaz*", and "h*"
respectively, then in most file systems the wildcard fields of the
name component of from-wildname and to-wildname are each "*", the
matching portion of source is "onk", and the name component of
result is "honk"; however, the exact behavior of translate-pathname
is not dictated by the Common Lisp language and may
vary according to the user interface conventions of the file systems
involved.

During the copying of a portion of source into result, additional
implementation-defined translations of alphabetic case or file naming
conventions may occur, especially when from-wildname and
to-wildname are for different hosts.

If any of the first three arguments is not a pathname, string, or file
stream, an error of type type-error is signaled. It is valid for
source to be a wild pathname; in general this will produce a wild
result pathname. It is valid for from-wildname or to-wildname or both
to be non-wild. An error is signaled if the source pathname does not
match the from-wildname, that is,
if (pathname-match-p sourcefrom-wildname) would not be true.

There are no specified keyword arguments for translate-pathname, but
implementations are permitted to extend it by adding keyword arguments.
There is one specified return value from translate-pathname;
implementations are permitted to extend it by returning additional
values.

Here is an implementation suggestion. One file system performs this operation by
examining corresponding pieces of the three pathnames in turn, where a piece is a
pathname component or a list element of a structured component such as
a hierarchical directory. Hierarchical directory elements in
from-wildname and to-wildname are matched by whether they are
wildcards, not by depth in the directory hierarchy. If the piece in
to-wildname is present and not wild, it is copied into the result.
If the piece in to-wildname is :wild or nil, the corresponding
piece in source is
copied into the result. Otherwise, the piece in to-wildname might be
a complex wildcard such as "foo*bar"; the portion of the piece in source
that matches the
wildcard portion of the corresponding piece in from-wildname (or the entire
source piece, if the from-wildname piece is not wild and therefore
equals the source piece) replaces the wildcard
portion of the piece in to-wildname and the value produced is used in
the result.

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

Here are some examples of the use of the new wildcard pathname facilities.
These examples are not portable. They are written to run
with particular file systems and particular wildcard conventions and are
intended to be illustrative, not prescriptive.
Other implementations may behave differently.

One cannot rely on rename-file to handle wild pathnames in a predictable
manner. However, one can use translate-pathname explicitly to control
the process.

(defun rename-files (from to)
"Rename all files that match the first argument by
translating their names to the form of the second
argument. Both arguments may be wild pathnames."
(dolist (file (directory from))
;; DIRECTORY produces only pathnames that match from-wildname.
(rename-file file (translate-pathname file from to))))

Assuming one particular set of popular wildcard conventions,
this function might exhibit the following behavior.
Not all file systems will run this example exactly as written.

The following examples are similar to the preceding examples
but use two different hosts; host U supports a UNIX file system
and host V supports a VAX/VMS file system. Note the translation
of file type (from l to LSP) and the change of alphabetic case conventions.

The next example is a version of the
function translate-logical-pathname (simplified a bit) for a logical host named FOO.
The points of interest are the use of pathname-match-p as
a :test argument for assoc and the use of translate-pathname
as a substrate for translate-logical-pathname.