2.17 Filenames


2.17.1 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 [see ANSI] and it can be roughly summarized as follows:

[hostname:][;][directory-item;]0 or more[name][.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 more[name][.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 signaled.

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.

NamestringNameTypeDirectoryDevice
"foo.lsp""foo""lsp"nilnil
".bashrc"".bashrc"nilnilnil
".ecl.lsp"".ecl""lsp"nilnil
"foo.*""foo":wildnilnil
"*.*":wild:wildnilnil
"ecl/build/bare.lsp""bare""lsp"(:relative "ecl" "build")nil
"ecl/build/"nilnil(:relative "ecl" "build")nil
"../../ecl/build/"nilnil(:relative :up :up "ecl" "build")nil
"/etc/"nilnil(:absolute "etc")nil
"C:/etc/"nilnil(:absolute "etc")"C"
".*"".*"nilnilnil
#.(make-pathname :type "*")nil:wildnilnil

Table 2.8: Examples of physical namestrings


2.17.2 Wild pathnames and matching

ECL accepts four kind of wildcards in pathnames.

The matching rules in Common Lisp 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 Dictionary.


2.17.3 C Reference

2.17.3.1 ANSI dictionary

Common Lisp and C equivalence

Lisp symbolC function
directory-namestringcl_object cl_directory_namestring(cl_object pathname)
enough-namestringcl_object cl_enough_namestring(cl_narg narg, cl_object pathname, ...)
file-namestringcl_object cl_file_namestring(cl_object pathname)
host-namestringcl_object cl_host_namestring(cl_object pathname)
load-logical-pathname-translationscl_object cl_load_logical_pathname_translations(cl_object host)
logical-pathname-translationscl_object cl_logical_pathname_translations(cl_object host)
logical-pathnamecl_object cl_logical_pathname(cl_object pathspec)
make-pathnamecl_object cl_make_pathname(cl_narg narg, ...)
merge-pathnamescl_object cl_merge_pathnames(cl_narg narg, cl_object pathname,...)
namestringcl_object cl_namestring(cl_object pathname)
parse-namestringcl_object cl_parse_namestring(cl_narg narg, cl_object thing, ...)
pathnamecl_object cl_pathname(cl_object pathspec)
pathname-devicecl_object cl_pathname_device(cl_narg narg, cl_object pathname, ...)
pathname-directorycl_object cl_pathname_directory(cl_narg narg, cl_object pathname, ...)
pathname-hostcl_object cl_pathname_host(cl_narg narg, cl_object pathname, ...)
pathname-match-pcl_object cl_pathname_match_p(cl_object pathname, cl_object wildcard)
pathname-namecl_object cl_pathname_name(cl_narg narg, cl_object pathname, ...)
pathname-typecl_object cl_pathname_type(cl_narg narg, cl_object pathname, ...)
pathname-versioncl_object cl_pathname_version(cl_object pathname)
pathnamepcl_object cl_pathnamep(cl_object object)
translate-logical-pathnamecl_object cl_translate_logical_pathname(cl_narg narg, cl_object pathname, ...)
translate-pathnamecl_object cl_translate_pathname(cl_narg narg, cl_object source, cl_object from_wildcard, cl_object to_wildcard, ...)
wild-pathname-pcl_object cl_wild_pathname_p(cl_narg narg, cl_object pathname, ...)