Echoing the last command run in Bash?
Bash has built in features to access the last command executed. But that's the last whole command (e.g. the whole case
command), not individual simple commands like you originally requested.
!:0
= the name of command executed.
!:1
= the first parameter of the previous command
!:*
= all of the parameters of the previous command
!$
= the final parameter of the previous command
!:-1
= all parameters in range 0-1 (inclusive)
!!
= the previous command line
etc.
So, the simplest answer to the question is, in fact:
echo !!
...alternatively:
echo "Last command run was ["!:0"] with arguments ["!:*"]"
Try it yourself!
echo this is a test
echo !!
In a script, history expansion is turned off by default, you need to enable it with
set -o history -o histexpand
The command history is an interactive feature. Only complete commands are entered in the history. For example, the case
construct is entered as a whole, when the shell has finished parsing it. Neither looking up the history with the history
built-in (nor printing it through shell expansion (!:p
)) does what you seem to want, which is to print invocations of simple commands.
The DEBUG
trap lets you execute a command right before any simple command execution. A string version of the command to execute (with words separated by spaces) is available in the BASH_COMMAND
variable.
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
…
echo "last command is $previous_command"
Note that previous_command
will change every time you run a command, so save it to a variable in order to use it. If you want to know the previous command's return status as well, save both in a single command.
cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi
Furthermore, if you only want to abort on a failed commands, use set -e
to make your script exit on the first failed command. You can display the last command from the EXIT
trap.
set -e
trap 'echo "exit $? due to $previous_command"' EXIT
Note that if you're trying to trace your script to see what it's doing, forget all this and use set -x
.
After reading the answer from Gilles, I decided to see if the $BASH_COMMAND
var was also available (and the desired value) in an EXIT
trap - and it is!
So, the following bash script works as expected:
#!/bin/bash
exit_trap () {
local lc="$BASH_COMMAND" rc=$?
echo "Command [$lc] exited with code [$rc]"
}
trap exit_trap EXIT
set -e
echo "foo"
false 12345
echo "bar"
The output is
foo
Command [false 12345] exited with code [1]
bar
is never printed because set -e
causes bash to exit the script when a command fails and the false command always fails (by definition). The 12345
passed to false
is just there to show that the arguments to the failed command are captured as well (the false
command ignores any arguments passed to it)