(In the following cat is a stand-in for "any command in $PATH".)

Consider this example:

% TMP=${:-=cat}
% FOO="blah blah blah $TMP blah blah blah"
% echo $FOO
blah blah blah /bin/cat blah blah blah

Direct interpolation of ${:-=cat} into the string does not achieve the same thing:

% FOO="blah blah blah ${:-=cat} blah blah blah"
% echo $FOO
blah blah blah =cat blah blah blah

Is there a wayto achieve the same end result as before (i.e. with /bin/cat rather than =cat in the final string) without having to create the intermediate variable TMP?

(Of course, the only reason to even consider a construct like ${:-=cat} instead of plain-ol' =cat is the hope of being able to interpolate it in a string. I was surprised to discover that it doesn't work...)


In zsh, = in form of =word is a special expansion operator, and will be expanded to the full path of the command named word if the command existed and the EQUALS option is set.

That expansion is not performed inside double quotes, so using ${:-=cat} inside double quotes won't work:

$ TMP="${:-=cat}"
$ print -rl -- $TMP

Now, you have several options to achieve the same thing you want.

Don't use double quotes around it:

$ FOO="blah blah blah "${:-=cat}" blah blah blah"
$ print -rl -- $FOO
blah blah blah /bin/cat blah blah blah

The zsh/parameter module provides the commands associative array, giving you access to the command hash table. You can use $commands[name] to get the full path of the name command:

$ zmodload zsh/parameter
$ print -rl -- $commands[cat]

Another option is to use the :c modifier:

$ var=cat
$ print -rl -- $var:c
$ print -rl "foo ${${:-cat}:c} bar"
foo /bin/cat bar

Of course, you can also use the standard command -v command:

$ print -rl -- "foo $(command -v cat) bar"
foo /bin/cat bar

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.