Let us assume to run the following commands creating links in the Windows prompt (terminal):

> mkdir fooDir
> echo hello> fooDir\foo
> mklink /d fooDirSym fooDir
> mklink /j fooDirJunc fooDir
> mklink /h fooDir\fooHard fooDir\foo
> cd fooDir
> mklink fooSym foo

Moving to Emacs, this works as expected:

(file-truename "path/to/fooDir/fooSym")
    => "path/to/fooDir/foo"
(file-nlinks "path/to/fooDir/foo")
    => 2 (#o2, #x2, ?\C-b)
 ;; The second name should be fooDir/fooHard
(file-truename "c:/p/fooDirSym")
    => "path/to/fooDir"


(file-truename "path/to/fooDirJunc")
    => "path/to/fooDirJunc"
(file-nlinks "path/to/fooDir/")
    => 1 (#o1, #x1, ?\C-a)

A Windows junction is not counted as a hard link (and in fact it is a soft link) and it is not a symlink.

The questions now are:

How do we identify the pathnames (not only the number) of hard links to foo?
How do we identify the presence and the path of junctions?

1 Answer 1


A solution based on Microsoft junction by Mark Russinovich.

(defun get-target (dir)
  "If DIR is a junction, return its target, else return DIR.
The 'junction' util is assumed to be in your path."  
  (setq dir (expand-file-name (substitute-in-file-name dir)))
  (let* (out (bin "junction.exe"))    
    (unless (executable-find bin) (error (concat "Unable to find the tool " bin)))
    (setq out (car (last (split-string
               (concat "junction "
                     "/" "\\\\"
                     (replace-regexp-in-string "/$" "" dir)))))
              "\n" t))))
    (if (string-match "^ +Substitute Name: " out)
    (expand-file-name (replace-match "" nil nil out)) dir)))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.