Function: file-chase-links
file-chase-links is a byte-compiled function defined in files.el.gz.
Signature
(file-chase-links FILENAME &optional LIMIT)
Documentation
Chase links in FILENAME until a name that is not a link.
Unlike file-truename, this does not check whether a parent
directory name is a symbolic link.
If the optional argument LIMIT is a number,
it means chase no more than that many links and then stop.
Other relevant functions are documented in the file group.
Probably introduced at or before Emacs version 22.1.
Shortdoc
;; file
(file-chase-links "/tmp/foo/bar")
e.g. => "/tmp/foo/zot"
Source Code
;; Defined in /usr/src/emacs/lisp/files.el.gz
(defun file-chase-links (filename &optional limit)
"Chase links in FILENAME until a name that is not a link.
Unlike `file-truename', this does not check whether a parent
directory name is a symbolic link.
If the optional argument LIMIT is a number,
it means chase no more than that many links and then stop."
(let (tem (newname filename)
(count 0))
(while (and (or (null limit) (< count limit))
(setq tem (file-symlink-p newname)))
(save-match-data
(if (and (null limit) (= count 100))
(error "Apparent cycle of symbolic links for %s" filename))
;; In the context of a link, `//' doesn't mean what Emacs thinks.
(while (string-match "//+" tem)
(setq tem (replace-match "/" nil nil tem)))
;; Handle `..' by hand, since it needs to work in the
;; target of any directory symlink.
;; This code is not quite complete; it does not handle
;; embedded .. in some cases such as ./../foo and foo/bar/../../../lose.
(while (string-match "\\`\\.\\./" tem)
(setq tem (substring tem 3))
(setq newname (expand-file-name newname))
;; Chase links in the default dir of the symlink.
(setq newname
(file-chase-links
(directory-file-name (file-name-directory newname))))
;; Now find the parent of that dir.
(setq newname (file-name-directory newname)))
(setq newname (files--splice-dirname-file (file-name-directory newname)
tem))
(setq count (1+ count))))
newname))