# directory

`(directory pathspec)`

The pathnames matching `pathspec`, sorted with `string<` so the same program
prints the same answer on every backend whatever order the host hands entries
back in. `nil` when nothing matches -- it never signals.

A **wild name component** lists the directory and keeps what the pattern matches.
`*` stands for any sequence of characters, `?` for exactly one, and the answers
keep the pathspec's own directory prefix so each is directly openable, with a
subdirectory carrying a trailing `/`:

```lisp
(directory "no-such-directory/*.*")   ; => NIL
```

Given a directory holding `a.txt`, `b.txt` and the subdirectories `sub/` and
`empty/`:

| pathspec | answer |
|---|---|
| `"d/*.*"` | `(#P"d/a.txt" #P"d/b.txt" #P"d/empty/" #P"d/sub/")` — everything |
| `"d/*.txt"` | `(#P"d/a.txt" #P"d/b.txt")` |
| `"d/?.txt"` | `(#P"d/a.txt" #P"d/b.txt")` |
| `"d/*"` | `(#P"d/empty/" #P"d/sub/")` — a wild name with NO type, so only untyped entries |
| `"d/a*"` | `NIL` — same rule: `a.txt` has a type |

A **non-wild pathspec designates itself**, as in Common Lisp: `"d/a.txt"` answers
`(#P"d/a.txt")` when the file exists, and a directory answers itself in directory
form -- both `"d"` and `"d/"` give `(#P"d/")`. **Listing a directory is
`"d/*.*"`, not `"d/"`.**

A **wild directory component** expands the prefix before the name is matched.
`*` walks exactly one level and `**` walks the whole subtree -- and, as in Common
Lisp, `**` matches ZERO levels as well as many, so the base directory's own files
come back too:

| pathspec | answer |
|---|---|
| `"d/*/*.lisp"` | the `.lisp` files one level below `d/` |
| `"d/**/*.lisp"` | every `.lisp` file in `d/` and anywhere below it |
| `"d/**/"` | `d/` itself and every directory below it |

Every expectation above is the same answer SBCL gives for the same tree.

## Backend support

All four backends, through one primitive each: the source-loader abstraction on
the interpreter (so a host without a filesystem, such as the browser playground,
answers `nil` rather than failing), `java.io.File.list` on the JVM, and WASI
`fd_readdir` on both WASM backends -- Preview 1 binds the real host function,
`--component` an adapter over `wasi:filesystem`'s `read-directory`. A WASM module
resolves the path against its preopened directories -- a relative path against the
first one, an absolute path against the preopened directory whose name is its
longest prefix -- so run it with `--dir`; without one nothing matches.

The `.` and `..` self/parent entries are never returned on any backend.

Everything else in the family -- `uiop:directory-files`, `uiop:subdirectories`,
`uiop:collect-sub*directories` and `uiop:directory-exists-p` -- is defined in
terms of this one function.
