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.

View in manual

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