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))