Bash: “history number” vs “command number”

bashcommand historycommand line

While Googling how to customize my shell prompt via the PS1 variable, I'm seeing tables of special characters that can be used. In particular:

          \!     the history number of this command
          \#     the command number of this command

"History number" seems to be more commonly used, and I know how to use commands like !523 to redo commands from history. But I can't figure out if "command number" has similar functionality. I've tried putting \# in my PS1 variable, and it seems to output the number of commands entered in a particular session (unlike \!, which persists after logout/exit).

Anyone know how to use "command number" in a convenient or meaningful way?

Best Answer

Bash's command number is for display only.

First, some background from bashref:

The command number and the history number are usually different: the history number of a command is its position in the history list, which may include commands restored from the history file (*note Bash History Facilities::), while the command number is the position in the sequence of commands executed during the current shell session.

Diving through the source, in parse.y we see that '\#' resolves to the global static variable current_command_number:

case '#':                                                                     
  n = current_command_number;                                                 
  /* If we have already incremented current_command_number (PS4,              
 ${var@P}), compensate */                                                     
  if (orig_string != ps0_prompt && orig_string != ps1_prompt && orig_string != ps2_prompt)
n--;                                                                          
  temp = itos (n);                                                            
  goto add_string;                                                            

which only has one other use: in eval.c, it's incremented upon running a command:

# ...
current_command_number++;                                                  

executing = 1;                                                             
stdin_redir = 0;                                                           

execute_command (current_command);                                         

All that's kept is a number, not the actual command or even the equivalent history number. So, upon execution of each command, bash forgets what command associated with what command number, rendering the command number unusable for anything other than display and scroll reference.

Related Question