Let's say that in my .zshrc I have:

alias ls='ls --color=auto'
alias ll='ls -halF'

As expected, whence ls returns ls --color=auto, and whence ll returns ls -halF.

Is there any option (nothing in help whence helped) or one-liner such that <rwhence> ll will produce ls --color=auto -halF, or similar?

2 Answers 2


First we confirm that aliases do indeed recurse when used under a sane configuration...

% PS1='%% ' zsh -f
% alias echo='echo foo'
% echo mlatu
foo mlatu
% alias xxxx='echo bar'
% xxxx gerku
foo bar gerku

Indeed they do. A study of the options for whence in zshall(1) does not reveal any option that does the recursion, so let's try writing something.

function rwhence {
    local def
    local -a alias
    def=$(builtin whence -v $1)
    print $def
    if [[ $def == *'is an alias for'* ]]; then
        # simplification: assume global aliases do not exist
        alias=( ${(z)def##*is an alias for } )
        # loop detection only at the immediate level
        if [[ $alias[1] != $1 ]]; then
            rwhence $alias[1]

Basically we parse the output of whence -v, look for an alias definition, and if so pull the first command word out of that and if that is not what we're already looking at, recurse. Global aliases (which I do not ever use) would be more complicated to support.

% rwhence xxxx
xxxx is an alias for echo bar
echo is an alias for echo foo
% rwhence echo
echo is an alias for echo foo
% rwhence cat
cat is /bin/cat
% rwhence mlatu
mlatu not found

You can use the fact that aliases are expanded upon function definition:

expand_alias() {
  print -r -- ${functions[_alias_]}


$ alias 'a=a;b'
$ alias 'b=b;a x'
$ alias -g 'x=foo'
$ expand_alias a
    a foo

(of course running that expanded alias is not the same as running a unless you disable alias expansion).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .