According to the Bash manual, the environment variable
The command currently being executed or about to be executed, unless the shell is executing a command as the result of a trap, in which case it is the command executing at the time of the trap.
Taking that trap corner case aside, if I understand correctly this means that when I execute a command, the variable
BASH_COMMAND contains that command. It's not absolutely clear whether that variable is unset after the command execution (i.e., is only avaialble while the command is running, but not after), though one might argue that since it is "the command currently being executed or about to be executed", it is not the command that was just executed.
But let's check:
$ set | grep BASH_COMMAND= $
Empty. I would have expected to see
BASH_COMMAND='set | grep BASH_COMMAND=' or maybe just
BASH_COMMAND='set', but empty surprised me.
Let's try something else:
$ echo $BASH_COMMAND echo $BASH_COMMAND $
Well that makes sense. I execute the command
echo $BASH_COMMAND and so the variable
BASH_COMMAND contains the string
echo $BASH_COMMAND. Why did it work this time, but not before?
Let's do the
set thing again:
$ set | grep BASH_COMMAND= BASH_COMMAND='echo $BASH_COMMAND' $
So wait. It was set when I executed that
echo command, and it was not unset afterwards. But when I executed
BASH_COMMAND was not set to the
set command. No matter how often I execute the
set command here, the result stays the same. So, is the variable set when executing
echo, but not when executing
set? Let's see.
$ echo Hello AskUbuntu Hello AskUbuntu $ set | grep BASH_COMMAND= BASH_COMMAND='echo $BASH_COMMAND' $
What? So the variable was set when I executed
echo $BASH_COMMAND, but not when I executed
echo Hello AskUbuntu? Where's the difference now? Is the variable only set when the current command itself actually forces the shell to evaluate the variable? Let's try something different. Maybe some external command this time, not a bash builtin, for a change.
$ /bin/echo $BASH_COMMAND /bin/echo $BASH_COMMAND $ set | grep BASH_COMMAND= BASH_COMMAND='/bin/echo $BASH_COMMAND' $
Hmm, ok… again, the variable was set. So is my current guess correct? Is the variable only set when it has to be evaluated? Why? Why? For performance reasons? Let's do one more try. We'll try to grep for
$BASH_COMMAND in a file, and since
$BASH_COMMAND should then contain a
grep should grep for that
grep command (i.e., for itself). so let's make an appropriate file:
$ echo -e "1 foo\n2 grep\n3 bar\n4 grep \$BASH_COMMAND tmp" > tmp $ grep $BASH_COMMAND tmp grep: $BASH_COMMAND: No such file or directory tmp:2 grep <-- here, the word "grep" is RED tmp:4 grep $BASH_COMMAND tmp <-- here, the word "grep" is RED tmp:2 grep <-- here, the word "grep" is RED tmp:4 grep $BASH_COMMAND tmp <-- here, the word "grep" is RED $ set | grep BASH_COMMAND= BASH_COMMAND='grep --color=auto $BASH_COMMAND tmp' $
Ok, interesting. The command
grep $BASH_COMMAND tmp got expanded to
grep grep $BASH_COMMAND tmp tmp (the variable gets expanded just that once, of course), and so I grepped for
grep, once in a file
$BASH_COMMAND which doesn't exist, and twice in the file
Q1: Is my current assumption correct that:
BASH_COMMANDis only set when a command tries to actually evaluate it; and
- it is not unset after execution of a command, even though the description may lead us to believe so?
Q2: If yes, why? Performance? If no, how else can the behavior in the above command sequence be explained?
Q3: Lastly, is there any scenario in which this variable could actually be meaningfully used? I was actually trying to use it within
$PROMPT_COMMAND to analyze the command being executed (and do some stuff depending on that), but I can't, because as soon as, within my
$PROMPT_COMMAND, I execute a command to look at the variable
$BASH_COMMAND, the variable gets sets to that command. Even when I do
MYVARIABLE=$BASH_COMMAND right at the beginning of my
MYVARIABLE contains the string
MYVARIABLE=$BASH_COMMAND, because an assignment is a command too. (This question is not about how I could obtain the current command within a
$PROMPT_COMMAND execution. There are other ways, I know.)
It's a bit like with Heisenberg's uncertainty principle. Just by observing the variable, I change it.