7

I want to get the expansion of an alias.

For example, if I have:

alias g=hub
alias cdh='cd $HOME'

I want to have:

expand_alias g == hub

expand_alias cdh == cd $HOME

The tricky thing is that the two shells have different output: bash:

$ alias g cdh
alias g='git'
alias cdh='cd $HOME'

zsh:

% alias g cdh
g=hub
cdh='cd $HOME'

Note no alias prefix and no quotes around hub.

8
  • 1
    So what exactly are you missing?
    – RudiC
    Commented Aug 18, 2018 at 10:16
  • 2
    Note that the zsh output is the standard one. bash will give you that one as well when in POSIX mode. Commented Aug 18, 2018 at 18:06
  • why are the single quotes a problem? Commented Aug 19, 2018 at 6:04
  • @HennoBrandsma I want to define an alias based on the contents of an existing one.
    – Tom Hale
    Commented Aug 19, 2018 at 7:03
  • 1
    Note that cd without arguments already brings you to $HOME Commented Aug 20, 2018 at 15:56

5 Answers 5

9

In zsh, you can just use

get_alias() {
  printf '%s\n' $aliases[$1]
}

With bash (assuming it's not in POSIX mode in which case its alias would give an output similar to zsh's), you could do:

get_alias() (
  eval '
    alias() { printf "%s\n" "${1#*=}"; }'"
    $(alias -- "$1")"
)

Basically, we evaluate the output of alias after having redefined alias as a function that prints what's on the right of the first = in its first argument.

You could use a similar approach for something compatible with most POSIX shells, zsh and bash:

get_alias() {
  eval "set -- $(alias -- "$1")"
  eval 'printf "%s\n" "${'"$#"'#*=}"'
}
2
  • I wondered why parentheses are used instead of the usual braces... a function body can be a single statement, and in this case that's a subshell.
    – Tom Hale
    Commented Aug 19, 2018 at 5:50
  • 1
    @TomHale, that's to limit the scope of that alias function we declare. Commented Aug 19, 2018 at 6:35
3

Based on Stéphane Chazelas' answer, I came up with:

function alias_expand {
  if [[ $ZSH_VERSION ]]; then
    # shellcheck disable=2154  # aliases referenced but not assigned
    [ ${aliases[$1]+x} ] && printf '%s\n' "${aliases[$1]}" && return
  else  # bash
    [ "${BASH_ALIASES[$1]+x}" ] && printf '%s\n' "${BASH_ALIASES[$1]}" && return
  fi
  false  # Error: alias not defined
}

(with bash 4.0 or newer).

2
  • 1
    function force-expand { local e="$(expand_alias "$1")" ; test -z "$e" && e="$1" ; echo "$e" }
    – HappyFace
    Commented Jun 19, 2019 at 13:28
  • @HappyFace Cheers for pointing out the issue with the return value. Answer updated.
    – Tom Hale
    Commented Aug 10, 2020 at 11:07
0

How about defining a shell function:

EXA() { alias $@ | sed 's/^/expand_/; s/=/ == /; s/\o047//g; '; }
5
  • Syntax error when I copy and paste
    – Tom Hale
    Commented Aug 19, 2018 at 5:12
  • show the syntax error.
    – RudiC
    Commented Aug 19, 2018 at 6:48
  • unmatched '. How will this remove single quotes?
    – Tom Hale
    Commented Aug 19, 2018 at 8:34
  • Rats! Corrected typo...
    – RudiC
    Commented Aug 19, 2018 at 10:57
  • Breaks with: alias ls='colourify ls -CF --block-size=\'\''1 --color=always --quoting-style=shell-escape'
    – Tom Hale
    Commented Aug 22, 2018 at 8:23
0

My zsh had this bound to a key combo:

_expand_alias () {
    local word expl tmp pre sel what
    local -a tmpa suf
    eval "$_comp_setup"
    if [[ -n $funcstack[2] ]]
    then
        if [[ "$funcstack[2]" = _prefix ]]
        then
            word="$IPREFIX$PREFIX$SUFFIX"
        else
            word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX"
        fi
        pre=()
    else
        local curcontext="$curcontext"
        if [[ -z "$curcontext" ]]
        then
            curcontext="expand-alias-word:::"
        else
            curcontext="expand-alias-word:${curcontext#*:}"
        fi
        word="$IPREFIX$PREFIX$SUFFIX$ISUFFIX"
        pre=(_main_complete - aliases)
    fi
    zstyle -s ":completion:${curcontext}:" regular tmp || tmp=yes
    case $tmp in
        (always) sel=r  ;;
        (yes | 1 | true | on) [[ CURRENT -eq 1 ]] && sel=r  ;;
    esac
    zstyle -T ":completion:${curcontext}:" global && sel="g$sel"
    zstyle -t ":completion:${curcontext}:" disabled && sel="${sel}${(U)sel}"
    tmp=
    [[ $sel = *r* ]] && tmp=$aliases[$word]
    [[ -z $tmp && $sel = *g* ]] && tmp=$galiases[$word]
    [[ -z $tmp && $sel = *R* ]] && tmp=$dis_aliases[$word]
    [[ -z $tmp && $sel = *G* ]] && tmp=$dis_galiases[$word]
    if [[ -n $tmp ]]
    then
        tmp=${tmp%%[[:blank:]]##}
        if [[ $tmp[1] = [[:alnum:]_] ]]
        then
            tmpa=(${(z)tmp})
            if [[ $tmpa[1] = $word && $tmp = $aliases[$word] ]]
            then
                tmp="\\$tmp"
            fi
        fi
        zstyle -T ":completion:${curcontext}:" add-space || suf=(-S '')
        $pre _wanted aliases expl alias compadd -UQ "$suf[@]" -- ${tmp%%[[:blank:]]##}
    elif (( $#pre )) && zstyle -t ":completion:${curcontext}:" complete
    then
        $pre _aliases -s "$sel" -S ''
    else
        return 1
    fi
}
0

In my zsh environment, when I type alias with no command I get on stdout a list of all aliases. The same happens in bash (on MacOS both). These are in a form alias=expansion

So you could filter further with sed: alias | sed -ne 's/cdh=\(.*\)$/\1/p' if "cdh" is the alias you want to know. You could make a shell function in your profile for this, if this is a common task for you: like

expand_alias() { alias $@ | sed -ne 's/^'$@'=\(.*\)$/\1/p' }
4
  • This leaves the single quotes in. Please re-read the question.
    – Tom Hale
    Commented Aug 19, 2018 at 5:10
  • @TomHale Inthe OP's example, it's not quite clear to me why the single quotes are a problem. They don't hurt for single commands, or one word substitutions; they are needed for commands with spaces. So that's why I left in the spaces, as I don't want to complicate things by adding logic to remove unnecessary single quotes. If they always have to go, just add ` | tr -d \' ` to the pipe. Commented Aug 19, 2018 at 6:04
  • Fair enough assumption. I can't upvote you again now. The | tr wouldn't allow for a ' in the middle of an alias though.
    – Tom Hale
    Commented Aug 19, 2018 at 7:06
  • this does not work as intended if there are = inside the alias. I will edit the answer with a fix for this :) Commented Oct 14, 2021 at 13:24

You must log in to answer this question.

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