Mattman
Mattman

Reputation: 88

Expand An Alias That Executes Another Alias (Nested Alias)

I have two aliases:

alias ls="ls -G"
alias la="ls -aFhlT"

I know that after you type your alias, but before you execute, you can type Meta-Control-e (probably Alt-Control-e, but possibly Esc-Control-e) to expand what you've typed.

So, if I expand my alias la using this method I get:

ls -aFhlT

However, what I really want is to see:

ls -G -aFhlT

Is there any way to achieve this besides typing Meta-Control-e a second time?

--OR--

Is there any way to confirm that my execution of la actually executed ls -G -aFhlT (other than knowing how nested aliases work and trusting that it did what I think it did)?

I'm trying to do this on macOS, but a general bash solution will also be accepted.

Upvotes: 2

Views: 2084

Answers (1)

Mattman
Mattman

Reputation: 88

This question rides the fine line between using an alias and using a function. When aliases get even slightly complicated, it is generally better to write a function instead. That being said, I did find a solution for this question that allows for expanding aliases as desired.

I wrote a bash function for this:

xtrace() {
    local eval_cmd
    printf -v eval_cmd '%q ' "${@}"
    { set -x
      eval "${eval_cmd}"
    } 2>&1 | grep '^++'
    return "${PIPESTATUS[0]}"
}

The -v flag of printf will store the output of printf in the specified variable.

The printf format string %q will print the associated argument ($@ in this case) shell-quoted, reusable as input. This eliminates the dangers associated with passing arbitrary code/commands to eval.

I then use a command group { ... } so I can control the functionality of set -x, which tells bash to print a trace of all executed commands. For my purposes, I do not care about any output except for the fully expanded command, so I redirect stderr and grep for the output line that starts with "++". This will be the line that shows the fully expanded command.

Finally, I return the value of PIPESTATUS[0], which contains the return code of the last command executed in the command group (i.e. the eval command).

Thus, we will get something like the following:

$ xtrace la; echo $?
++ ls -G -aFhlT
0

Much thanks to @CharlesDuffy for the set -x recommendation as well as the input sanitation for eval.

Upvotes: 3

Related Questions