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?


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).

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.