From the documentation of
if it has a named directory as its prefix, that part is replaced by a
~ followed by the name of the directory, but only if the result is shorter than the full path
A reference follows to dynamic and static named directories. What you're seeing is a static named directory
They may also be defined if the text after the
~ is the name of a string shell parameter whose value begins with a
So if the value of the variable
~SOME_DIR is a static named directory whose value is
/home/bschlenk/some/path. The prompt expansion
/home/bschlenk/some/path and abbreviates it to
But that's not the whole story. In fact, the abbreviation only happens if
SOME_DIR has been “activated” by the use of
~SOME_DIR. This is documented under the option
auto_name_dirs, which removes the need for prior activation, but defaults off.
Any parameter that is set to the absolute name of a directory immediately becomes a name for that directory, that will be used by the
%~ and related prompt sequences, and will be available when completion is performed on a word starting with
~. (Otherwise, the parameter must be used in the form
A parameter that is activated for
%~ substitution (and completion after
~) shows up as an entry in the named directory hash table which you can list with
We've put the pieces together to understand what's going on. How can you solve your problem? It depends what caused
SOME_DIR to be activated.
If you have the option
auto_name_dirs turned on, then obviously you should turn it off.
If you've used
~SOME_DIR previously, you can deactivate it with
unhash -d SOME_DIR
This is not permanent: it'll pop up again if you use
~SOME_DIR again. But given that you can use
$SOME_DIR wherever you can use
~SOME_DIR is not a very useful feature.
If you can't get rid of what makes
SOME_DIR a named directory and you want to abbreviate the current directory with nothing but
~, you can implement this transformation manually.
if [[ $PWD = $HOME ]]; then
elif [[ $PWD = $HOME/* ]]; then
and then use
print -rn $HPWD instead of
print -Pn %~.
If you can't prevent
SOME_DIR from becoming a named directory and you can't change the code that uses
%~, it gets trickier. You can empty the directory hash table with
hash -r, but there's no way to make this local to a function (only to a subshell).