I have the following personalized theme activated with oh-my-zsh (latest version of zsh and oh-my-zsh):

local return_code="%(?..%{$fg[red]%}%? %{$reset_color%})"

local user_host='%{$terminfo[bold]$fg[green]%}%n @ %m%{$reset_color%}'
local current_dir='%{$terminfo[bold]$fg[cyan]%} %~%{$reset_color%}'
local rvm_ruby=''
local git_branch='$(git_prompt_info)%{$reset_color%}'

PROMPT="${user_host} %D{[%a, %b %d %I:%M:%S]} ${current_dir} ${rvm_ruby} ${git_branch}
%B$%b "

ZSH_THEME_GIT_PROMPT_SUFFIX="› %{$reset_color%}"

I have noticed that in the prompt, whenever I have an alias to a directory, it displays the name of the alias as my current directory as opposed to the actual path. While this is an interesting feature, I would like to disable that.

I am relatively new to oh-my-zsh, and I am not sure if this is an oh-my-zsh or zsh feature, but how can I disable it?


The prompt escape sequence %~ (included in $current_dir) expands to the current directory, taking abbreviations into account. The abbreviations are:

  • ~ for your home directory;
  • ~joe for the home directory of user joe;
  • ~foo for a named directory: the directory aliased to foo with hash -d foo=…;
  • ~[bar] for a dynamic named directory.

You can use %/ instead of %~. This never uses any directory abbreviation.

If you want to be fancier, you can execute your own code to determine how the current directory is displayed. One approach is to use a parameter substitution inside the prompt string. This requires the prompt_subst option to be set, which oh-my-zsh does (otherwise: setopt prompt_subst). The current directory is always available in the parameter PWD. Here's a simple version that only shortens your home directory to ~:

local current_dir='%{$terminfo[bold]$fg[cyan]%} ${${PWD/#%$HOME/~}/#$HOME\//~/}%{$reset_color%}'

${${PWD/#%$HOME/\~}/#$HOME\//\~/} means: if $PWD is exactly the same as $HOME, then set the result to ~, otherwise set the result to $PWD; then, if the current result begins with $HOME/, then replace this prefix by ~/, otherwise leave the result unchanged.

A clearer approach is to maintain a parameter containing a pretty-printed version of the current directory. Update this parameter in the chpwd hook function which is executed on every current directory change. Also initialize that parameter in your .zshrc.

There's only one chpwd function, so don't override oh-my-zsh's. Oh-my-zsh's chpwd calls the function in the array chpwd_functions, so add yours to the array.

function my_update_pretty_PWD {
  case $PWD in
    $HOME(/*)#) pretty_PWD=\~${PWD#$HOME};;
    *) pretty_PWD=$PWD;;
local current_dir='%{$terminfo[bold]$fg[cyan]%} ${pretty_PWD}%{$reset_color%}'

If you want to abbreviate users' home directories but not named directories, you can clear the home directories in a subshell and use the % parameter expansion flag to perform the automatic abbreviations in the subshell.

function my_update_pretty_PWD {
  pretty_PWD=$(hash -rd; print -lr -- ${(%)PWD})

Or if you prefer the inline approach:

local current_dir='%{$terminfo[bold]$fg[cyan]%} $(hash -rd; print -lr -- ${(%)PWD})%{$reset_color%}'
  • Fantastic explanation, as usual. Thanks Gilles! Apr 11 '13 at 13:31
  • The solution that adds the function my_update_pretty_PWD to chpwd_functions produces a slightly annoying behavior on my system (with zsh 5.0.2). Whenever I start the shell, the prompt does not show the current directory (whichever it may be, depending on where I start zsh from). The problem goes away as soon as I enter a cd command (cd . is enough). I also edited your inline solution because, after looking at the output, I noticed that it prints an an extra \ in the prompt (this is in the definition of local_current_dir). Apr 14 '13 at 2:43
  • @user815423426 Ah, right. Run my_update_pretty_PWD also once in your .zshrc. Apr 14 '13 at 8:49

The auto_name_dirs option is responsible for this behavior.

Use the command unsetopt auto_name_dirs to disable it.

  • Downvoter: would you please post a comment explaining why you downvoted my answer? I would like to learn.
    – user26112
    Apr 10 '13 at 23:33
  • 1
    auto_name_dirs doesn't affect named directories. It affects parameters that happen to be set to a directory name. Compare zsh -c 'hash -d here=$PWD; p="%~"; echo ${(%)p}' with zsh -c 'here=$PWD; echo ~here; p="%~"; echo ${(%)p}'. Apr 11 '13 at 1:39
  • 1
    My mistake. I thought variables containing directory names were directory aliases. (I use them as such.) I will read about named directories tonight. Thanks.
    – user26112
    Apr 11 '13 at 1:54
  • I think that auto_name_dirs is exactly the problem here. All environment variables (which point to a directory) get used when expanding '%~'. The are automatically added to the hash -d list. This does not appear to happen in your code example though, probably because it is not interactive?! But since the OP is using OMZ and they have this default, and I was just experiencing the same issue I am quite sure.
    – blueyed
    Nov 4 '13 at 17:29
  • This actually does work. I downvoted because it didn't seem to, but it does prevent new automatic name_dir entries, which solves the problem if done on login.
    – bukzor
    May 18 '16 at 21:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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