Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

So I asked this question about directory shortcuts in a shell. The idea is I'd like to be able to open a file in /home/Documents/foo, say, by typing C-x C-f ~foo/file.

So, is there a way to emulate zsh's "named directories" in the emacs buffer?

Incidentally, the shortcut definitions I want to use are already in my .zshrc, if there's a solution that reads them directly, that gets bonus points.

share|improve this question
Perhaps this isn't a unix SE question and I should try my luck on SU? – Seamus Sep 6 '10 at 20:17
this question isn't unix-specific (even down to the zsh part: there's a zsh port for Windows, or at least for Cygwin), so it should be on SU. But, well, it's here now, so I answered it here. – Gilles Sep 6 '10 at 22:16
up vote 7 down vote accepted

The Emacs component that's responsible for expanding ~ in file names is expand-file-name. Unfortunately, it's written in C, and deep inside its bowels is code that assumes that what comes after ~ is a user name. Fortunately, Emacs has a generic way of adding a wrapper around functions, so you can do what you want if you don't mind repeating some of the logic in the built-in function.

Here's some completely untested code that should get you going. Look up “Advising Emacs Lisp Functions” in the Emacs Lisp manual for more information; the basic idea is that defadvice adds some code to run before the actual code of expand-file-name. Please signal the mistakes I've inevitably made in comments (whether you know how to fix them or not).

(ad-define-subr-args 'expand-file-name '(name &optional default-directory))
(defvar expand-file-name-custom-tilde-alist
  '("foo" . "/home/Documents/foo"))
(defadvice expand-file-name (before expand-file-name-custom-tilde
                             activate compile)
  "User-defined expansions for ~NAME in file names."
    (if (string-match "\\`\\(\\(.*/\\)?~\\([^:/]+\\)\\)/" name)
        (let ((replacement (assoc (match-string 2 name) expand-file-name )))
          (if replacement
              (setq name (replace-match replacement t t name 1)))))))

I'll leave parsing the shortcuts in .zshrc to fill expand-file-name-custom-tilde-alist (or whatever technique you choose to keep the aliases in synch) as an exercise.

share|improve this answer

Simply use $foo instead of ~foo in the minibuffer. Emacs will treat foo as the name of an environment variable and use its value.

share|improve this answer
What a killer hidden feature! (remark: export the variable for them to be available) – AdrieanKhisbe Feb 15 '14 at 23:31

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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