ZSH Gem #11: Path and filename expansion

Posted by | Comments (6) | Trackbacks (0)

Yesterday I told you about Backtick expansion. Today I want to show you one more interesting expansion feature and that is path expansion for executable files.

I suppose you're familiar with the which command. With that command you can find out where an executable is located. So for example if you want to know which executable on the hard disk is called when you invoke the command cp you'd run:

which cp

and it would give you the name to the executable file (usually /bin/cp). For just looking up a path name you'd often prefer which over what I show you next simply because it can do some more stuff such as showing all occurrences in $PATH of this executable with the parameter -a. But the following ZSH feature isn't really meant to replace which.

Provided the EQUALS option is set (which is by default), each unquoted occurrence of = followed by one or more characters is treated as a command name. You can check that easily:

% =mv<TAB>

With the TAB key the expression =mv gets expanded to /bin/mv. The reason why I don't use the cp example from above is because the TAB completion of equal sign expressions doesn't work when the expression may be ambiguous. So if expansion of =mv doesn't work on your system and you get a list of executables starting with mv, you know why. But that is not the point. It is often not very expedient to use this kind command line expansion here (at least I can't think of any use for this).

However, you can use the equal sign operator like any other operator such as backticks. Those can be expanded with TAB as well but you don't have to. The same applies to = expressions. For instance:


The double equal sign is not a mistake. The first one is the normal assignment operator for shell variables, the second one the expansion operator. When you now run echo $myparam you won't get =cp as you might expect but /bin/cp.

You can use that anywhere. If you like typing more characters than needed, you can even start writing all your commands with an equal sign:

=ls dir

would be expanded to

/bin/ls dir

before it's executed (though you won't notice it).

Such a path expansion is sometimes helpful when you need absolute paths (e.g. you need to pass the path of an executable to another program). But of course you can also use it as a shorthand for which as I showed you above (at least as long as you don't need any of the more advanced features of which). With TAB completion directly on the command line it might be a little cumbersome which replacement, but in shell scripts you could definitely use it.


is definitely shorter than

listcmd=$(which ls)

although it might confuse others which are not so familiar with the ZSH syntax.

A similar expansion syntax also exists for directories. Instead of = you'd use ~ here,. I won't explain it here because that's a relatively complex topic. Let me just show you two little things: the one is an expansion expression for the current working directory (i.e. a shorthand for $PWD or `pwd`) and the second for the former working directory. They are ~+ and ~-. Other operators would be for handling the directory stack (you might know that feature from Bash and if not, follow the link below this article) or static named directories such as the home directories.

Read more about path and filename expansion:


No Trackbacks for this entry.


There have been 6 comments submitted yet. Add one as well!
Jim wrote on : (permalink)

This is wayyyy off-topic, but today I went past a gas station we have been to many times. It was a Shell station, but it has been bought by another company, called Z energy. IOW, they changed our Shell to Z. As I’ve been reading the series here daily, I thought it was hilarious :) Keep up the good work.

Per Wigren
Per Wigren wrote on : (permalink)

This is also a quick and nice way to avoid using aliases if you’ve used alias to change a command’s default parameters. It’s also good if you want to prevent aliases from using other aliases:

% alias ls=’ls —color’ % alias ls-nocolor=’=ls’

BobG wrote on : (permalink)

This is actually very handy when using the ‘chase’ command.

Forgot where your cc65 compiler was installed? Instead of chase $(which cc65) you can use:

% which =cc65 /usr/local/bin/cc65

Thanks for the tip!

BobG wrote on : (permalink)

Oh god, I’m way too tired. What I mean was that you can use:

% chase =cc65 /usr/local/stow/cc65-2.11.0/bin/cc65

Write a comment:

HTML-Tags will be converted to Entities.
Markdown format allowed
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

By submitting a comment, you agree to our privacy policy.

Design and Code Copyright © 2010-2021 Janek Bevendorff Content on this site is published under the terms of the GNU Free Documentation License (GFDL). You may redistribute content only in compliance with these terms. tweetbackcheck