## Filenames

### Syntax

A pathname in the file system of Common-Lisp consists of six elements: host, device, directory, name, type and version. Pathnames are read and printed using the `#P` reader macro followed by the namestring. A namestring is a string which represents a pathname. The syntax of namestrings for logical pathnames is well explained in the &ANSI; and it can be roughly summarized as follows:

    hostname:;directory-item;0 or morename.type.version
      hostname = word
      directory-item = wildcard-word
      type, name = wildcard-word without dots

Here, `wildcard-word` is a sequence of any character excluding `#\Null` and dots. `word` is like a `wildcard-word` but asterisks are excluded.

The way &ECL; parses a namestring is by first looking for the `hostname` component in the previous template. If it is found and it corresponds to a previously defined logical hostname, it assumes that the namestring corresponds to a logical pathname. If `hostname` is not found or it is not a logical hostname, then &ECL; tries the physical pathname syntax

    device://hostname/directory-item/0 or morename.type
      device, hostname = word
      directory-item = wildcard-word
      type = wildcard-word without dots
      name = .wildcard-word

If this syntax also fails, then the namestring is not a valid pathname string and a `parse-error` will be signalled.

It is important to remark that in &ECL;, all physical namestrings result into pathnames with a version equal to `:NEWEST`. Pathnames which are not logical and have any other version (i. e. `NIL` or a number), cannot be printed readably, but can produce a valid namestring which results of ignoring the version.

Finally, an important rule applies to physical namestrings: if a namestring contains one or more periods `.', the last period separates the namestring into the file name and the filetype. However, a namestring with a single leading period results in a name with a period in it. This is for compatibility with Unix filenames such as `.bashrc`, where the leading period indicates that the file is hidden.

The previous rule has in important consequence, because it means that if you want to create a pathname without a name, you have to do it explicitely. In other words, `".*"` is equivalent to `(MAKE-PATHNAME :NAME ".*" :TYPE NIL)`, while `(MAKE-PATHNAME :NAME NIL :TYPE :WILD)` creates a pathname whose type is a wildcard.

The following table illustrates how the physical pathnames work with practical examples.

### Examples of physical namestrings

Namestring | Name | Type | Directory | Device
"foo.lsp" | "foo" | "lsp" | NIL | NIL
".bashrc" | ".bashrc" | NIL | NIL | NIL
".ecl.lsp" | ".ecl" | "lsp" | NIL | NIL
"foo.*" | "foo" | :WILD | NIL | NIL
"*.*" | :WILD | :WILD | NIL | NIL
"ecl/build/bare.lsp" | "bare" | "lsp" | (:relative "ecl" "build") | NIL
"ecl/build/" | NIL | NIL | (:relative "ecl" "build") | NIL
"../../ecl/build/" | NIL | NIL | (:relative :up :up "ecl" "build") | NIL
"/etc/" | NIL | NIL | (:absolute "etc") | NIL
"C:/etc/" | NIL | NIL | (:absolute "etc") | "C"
".*" | ".*" | NIL | NIL | NIL
#.(MAKE-PATHNAME :TYPE "*") | NIL | :WILD | NIL | NIL

### Wild pathnames and matching

&ECL; accepts four kind of wildcards in pathnames.

- A single wildcard in a directory component, file name, type or version is parsed as the :WILD value. See for instance `"*.*"`, `"/home/*/.bashrc"`, etc

- A double wildcard in a directory component, such as in `"/home/**/"` is parsed as the :WILD-INFERIORS, and matches any number of directories, even nested ones, such as: `/home/`, `/home/jlr`, `/home/jlr/lib`, etc.

- An isolated wildcard `"log*.txt"` matches any number of characters: `log.txt`, `log_back.txt`, etc.

- A question mark `"log?.txt"` matches a single character: `log1.txt`, `log2.txt`...

The matching rules in &CommonLisp; and &ECL; are simple but have some unintuitive consequences when compared to Unix/DOS rules. The most important one is that directories must always end with a trailing slash `/`, as in `#p"/my/home/directory/"`. Second to that, NIL values can only be matched by NIL and :WILD. Hence, `"*"` can only match files without file type. For some examples see ansi.files.directory.