24.6.2 Distinguishing Kinds of Files

This section describes how to distinguish various kinds of files, such
as directories, symbolic links, and ordinary files.

Function: file-symlink-pfilename

If the file filename is a symbolic link, the
file-symlink-p function returns its (non-recursive) link target
as a string. (The link target string is not necessarily the full
absolute file name of the target; determining the full file name that
the link points to is nontrivial, see below.) If the leading
directories of filename include symbolic links, this function
recursively follows them.

If the file filename is not a symbolic link, or does not exist,
file-symlink-p returns nil.

Here are a few examples of using this function:

(file-symlink-p "not-a-symlink")
⇒ nil

(file-symlink-p "sym-link")
⇒ "not-a-symlink"

(file-symlink-p "sym-link2")
⇒ "sym-link"

(file-symlink-p "/bin")
⇒ "/pub/bin"

Note that in the third example, the function returned sym-link,
but did not proceed to resolve it, although that file is itself a
symbolic link. This is what we meant by “non-recursive” above—the
process of following the symbolic links does not recurse if the link
target is itself a link.

The string that this function returns is what is recorded in the
symbolic link; it may or may not include any leading directories.
This function does not expand the link target to produce a
fully-qualified file name, and in particular does not use the leading
directories, if any, of the filename argument if the link target
is not an absolute file name. Here’s an example:

(file-symlink-p "/foo/bar/baz")
⇒ "some-file"

Here, although /foo/bar/baz was given as a fully-qualified file
name, the result is not, and in fact does not have any leading
directories at all. And since some-file might itself be a
symbolic link, you cannot simply prepend leading directories to it,
nor even naively use expand-file-name (see File Name Expansion) to produce its absolute file name.

For this reason, this function is seldom useful if you need to
determine more than just the fact that a file is or isn’t a symbolic
link. If you actually need the file name of the link target, use
file-chase-links or file-truename, described in
Truenames.

The next two functions recursively follow symbolic links at
all levels for filename.

Function: file-directory-pfilename

This function returns t if filename is the name of an
existing directory, nil otherwise.

(file-directory-p "~rms")
⇒ t

(file-directory-p "~rms/lewis/files.texi")
⇒ nil

(file-directory-p "~rms/lewis/no-such-file")
⇒ nil

(file-directory-p "$HOME")
⇒ nil

(file-directory-p
(substitute-in-file-name "$HOME"))
⇒ t

Function: file-regular-pfilename

This function returns t if the file filename exists and is
a regular file (not a directory, named pipe, terminal, or
other I/O device).