The bash history can do many helpful things, and the search with Strg-r
that Terry Wang mentioned is an important one among them. But it is also possible to do exactly what you asked for.
You can re-do the previous command with !!
. With this, you can also edit the previous command. If for example you forgot to get root privileges for a command
apt-get install a-long-list-of-packages
you don't have to retype all of that again. Instead just call
sudo !!
If you want to re-execute the command at a specific position from your history, you can also use !
, for example
!3
to re-execute the command at position 3. Be aware that this counts from the top. So if you're storing 500 commands in your history, !1
would be "500 commands ago". You can also use negative numbers. For example
!-2
would re-execute the second last command.
You can also re-execute the last command that started with a string like
!apt-
which would re-do the last line that started with "apt-". If you want the last command where the string appeared anywhere in the line, you can use something like
!?pt-ge
There are more interesting things the bash history can do. Just to give an impression of the wide range of possibilities, you can specifically access a parameter of a command from history. So
!-5:3:p
would print the third parameter to the fifth from last command.
EDIT: Regarding Rudie's comment below, with the standard settings this bash history expansions are indeed executed directly. It's probably best described like this: A call like !-3
is replaced by the shell with the third last command from your history and then your input (with the replacement) executed. So if you type !-3
and press ENTER
and your third last command was ls ~
, it's in effect the same as if you typed ls ~
again and pressed ENTER
"on your own".
If you don't want that, you can set the shell option histverify
. For setting and unsetting shell options, you might want to read up on the shopt
command. With histverify
set, a call like !-3
only writes the replacement from your history to your command line, but doesn't execute it directly. You have, so to speek, press the crucial ENTER
yourself - or refrain from it, if you choose to.
I can't know what happened without access to your machine but here is a short explanation of how the history system works which might help you figure out what happened.
Each open terminal has its own history buffer. These buffers are appended to your $HISTFILE
when the terminal is closed (maybe also whenever the buffer is filled, but I don't know how often that happens). Now, the way to search for a command in your history is to simply run:
history | grep command
But if the command was run in a different shell, you won't see it in the history of your current one. To fix that, you close all open shells, open a new terminal window and search your history again.
If that still doesn't help, you've probably passed the threshold of commands stored in the $HISTFILE
. The behavior of the $HISTFILE
is controlled by various environment variables (see man bash
for the full list), but the relevant ones here are:
HISTSIZE
The number of commands to remember in the command history (see HISTORY below). If the value is 0, commands are not saved in the history list. Numeric values less than
zero result in every command being saved on the history list (there is no limit). The shell sets the default value to 500 after reading any startup files.
HISTFILESIZE
The maximum number of lines contained in the history file. When this variable is assigned a value, the history file is truncated, if necessary, to contain no more than
that number of lines by removing the oldest entries. The history file is also truncated to this size after writing it when a shell exits. If the value is 0, the history
file is truncated to zero size. Non-numeric values and numeric values less than zero inhibit truncation. The shell sets the default value to the value of HISTSIZE after
reading any startup files.
The higher values you set these to, the more commands you'll keep in your $HISTFILE
. For example, I use:
HISTSIZE=999999
HISTFILESIZE=999999
If you want to import the history from one shell into another, you can use the history
command:
$ help history | grep -E -- '-a|-r'
-a append history lines from this session to the history file
-r read the history file and append the contents to the history
So, run history -a
to write the history from one terminal and then history -w
to read it from the another. Now, running history
will show you the history of both shells.
Finally, you can make all your terminals share the same history by adding these lines to your ~/.bashrc
:
## history -a causes the last command to be written to the
## history file automatically and history -r imports the history
export PROMPT_COMMAND='history -a;history -r'
I also suggest you add this:
## Make Bash append rather than overwrite the history on disk:
shopt -s histappend
Best Answer
There’s no need to use
fc
if you just need the current command line, as the shell variableBASH_COMMAND
holds exactly that. I’d just trap theDEBUG
signal and use this variable as before, e.g.:This also has the advantage that it doesn’t write anything to the log if you just press Enter –
fc
just reads the last entry from the history list. Unfortunately I wasn’t able to test yourlogger
command on my system, but you sound like it worked fine, so this should work as well:Example run
Note how
alias
es likels
, empty lines (Enter) and typo’d commands are logged.