20

I have a bash function (or alias), for instance function install() {sudo apt-get install $@}. When running the command install dicelab, what I expect will actually be run is sudo apt-get install dicelab. Where can I see what was actually run by the shell? I would like to make sure that my more complicated aliases are working as expected.

  • Is that $@ part of your alias? Remember that aliases don't really support arguments, that will expand to the positional parameters (if any) of the context calling the alias. The usual way of running somealias some args works just by expanding the alias and leaving the arguments to follow it. If you actually want to be able to access the arguments, use a function, and quote the "$@" – ilkkachu May 4 '17 at 7:54
  • 2
    Possible duplicate of Resolve nested aliases to their source commands – DarkHeart May 4 '17 at 8:13
  • 1
    @AlonAviv, Good. :) Still, best get in the habit of quoting that "$@", arguments with whitespace or glob characters will burn otherwise. – ilkkachu May 4 '17 at 8:53
  • 1
    @DarkHeart This no duplicate. The other question is not concerned with shell functions. – Kusalananda May 4 '17 at 10:00
  • 2
    Neither was this one until it was edited to completely change its subject (and invalidate one of the existing answers). – Michael Homer May 4 '17 at 10:19
29

Use set -x in the shell.

$ alias hello='echo hello world!'
$ hello
hello world!

$ set -x
$ hello
+ echo hello world!
hello world!

Using set -x turns on the xtrace shell option (set +x turns it off) and should work in all Bourne-like shells, like bash, dash ksh93, pdksh and zsh. This prompts the shell to display the command that gets executed after alias expansions and variable expansions etc. has been performed.

The output will be on the standard error stream of the shell (just like the ordinary prompt) so it will not interfere with redirections of standard output, and it will be preceded by a prompt as defined by the PS4 shell variable (+␣ by default).

Example with a few functions:

$ world () { echo "world"; }
$ hello () { echo "hello"; }
$ helloworld () { printf '%s %s!\n' "$(hello)" "$(world)"; }

$ helloworld
hello world!

$ set -x
$ helloworld
+ helloworld
++ hello
++ echo hello
++ world
++ echo world
+ printf '%s %s!\n' hello world
hello world!

I'm running with set -x in all my interactive shells by default. It's nice to see what actually got executed... but I've noticed that programmable tab completion etc. may cause unwanted trace output in some shells.

14

You could use shell-expand-line, which is bound to Control-Alt-e by default:

$ bind -p | grep shell-expand-line
"\e\C-e": shell-expand-line

Among other things, it will replace aliases in the current line with their definition so you can see a command you're still going to run. Example:

$ install dicelab # now press C-Alt-e
$ sudo apt-get install  dicelab # the above line will be replaced with this
1

You can use the bash builtin type in order to see an alias or a function definition you are going to run:

$ type ls
ls is aliased to `ls --color=auto -p'

$ type -a ls
ls is aliased to `ls --color=auto -p'
ls is /bin/ls

$ install() { sudo apt-get install "@"; }

$ type install
install is a function
install () 
{ 
    aptitude install "@"
}

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.