------------------------------------------------------------------------------- Shell (BASH) History Note: Bash has history in two places: In memory and saved to ".bash_hisory" However that means when you have multiple terminal windows you have lots of copies of the bash history file in memory, and all later additions in each shell will be different. See "shopt -s histappend" though that does not help much! Only the terminal that last exits will actually update the history file! One of the best in-depth explainations on handling multi-line command history (in-memory and on-disk)... https://unix.stackexchange.com/a/353407/68648 ------------------------------------------------------------------------------- Caveats and Notes * HISTCONTROL=ignoredups:erasedups equivelent to HISTCONTROL=ignoreboth The erasedups ONLY works for the current line before it is added to history! * history -a does not trigger erasing duplicates See previous! * erasedups does not trim leading and trailing spaces when comparing commands * history -r can't seem to read from stdin (pipeline) * history -n read and append unread history, is buggy! DO NOT USE https://unix.stackexchange.com/a/525406/68648 ------------------------------------------------------------------------------- Bash v4 WARNING Reading bash history with mutli-line commands (and timestamp seperators) does not preserve the mutli-line commands. The first line will have the correct timestamp but later lines are put in-memory as seperate commands, and timestamped with the time command was read in. Set up shopt -s cmdhist shopt -s lithist HISTTIMEFORMAT='' Save a multi-line command into a history file history -c echo ' a ' history -w t cat t As you can see history is history -c history -r t history kill -9 $$ # ensure history is not SAVED from this shell ------------------------------------------------------------------------------- General helper commands Other useful history command shortcuts # history: list last, clear, reset, edit, don't save h() { history 30; } # last history commands executed hc() { source ~/bin/functions/history_clean.bash; echo "history cleaned"; } hr() { history -c; history -r; echo "history reset"; } he() { source ~/bin/functions/history_edit.bash; } # edit history (see below) hd() { unset HISTFILE; echo "history write disabled"; } For sources functions, see "Sensitive Information" section below) What command do you use the most (number of variants, due to 'erasedups') history | awk '{print $2}' | sort | uniq -c | sort -n | tail # The above could separate out piped commands too # awk 'BEGIN {FS="|"}{print $1}' Ignore extremely common commands you don't need to save to history Patterns must match the entire line being saved HISTIGNORE='&:rc:bg:fg:j:jobs:jobs *:history:history *' Or ignore all commands without arguments (untested) HISTIGNORE="!(+(*\ *))" I generally use HISTCONTROL='erasedups' to this to keep the history file getting too big with repeated commands, such as 'ls'. Though I also add 'ls' to the $HISTIGNORE list too. ------------------------------------------------------------------------------- Sensitive Information... Preventing sensitive information (like passwords) being saved to history. Use HISTCONTROL='ignorespace' so command starting with space does not go into history. That way if you know you will have a password on a line, you can tell it to not save it to history. HOWEVER, I prefer not to do this as I often copy and paste from pre-prepared text files with space indenting. Such commands will not get saved into history if this option is used, and I want them saved so I can edit and adjust them for later runs. Instead I have a 'he' or 'history_edit' function (source script) which lets me edit the in memory, history and erase or modify the offending command. Edit in-memory history (manual edit/delete unwanted history) =======8<-------- history -w /tmp/hist.$$ vim + /tmp/hist.$$ history -c history -r /tmp/hist.$$ rm /tmp/hist.$$ =======8<-------- Also I find there are commands I like to have in history, as I am working with them in some session, but which I generally do not want saved into the history file. That is they are semi-sensitive, or just not used outside particular terminal sessions. For example commands such as: encryption work, mounting/unmounting, downloading, video watching and editing, web page processing, etc. These commands I automatically remove from in-memory history, before the shell saves it out to the history save file, and on shell startup I do this by creating a 'hc' or 'history_clean' function. Basically it automatically removed anything I don't want in my history I call it from my ".bash_logout", or whenever I finish, such work. History Clean function (basic example)... =======8<-------- history -w /dev/stdout | perl -pe '$_="" if /^(:|mount|mencoder)/ || /(http:|https:|\/mnt)/' \ > /tmp/hist.$$ history -c history -r /tmp/hist.$$ history -w # Update the recorded history file shred -u /tmp/hist.$$ || rm -f /tmp/hist.$$ =======8<-------- ------------------------------------------------------------------------------- Update of history across all terminals (on fly) https://unix.stackexchange.com/questions/1288/ This is an option in "zsh", and tried to be replicated in "bash". It isn't easy however as the ideal solution is to do it as soon as user presses return, before the just entered command is executed. Basically as that command may run for a long time. Ultimate Solution... https://github.com/pts/pts-merge-history-bash/ based on... http://hints.macworld.com/dlfiles/preexec.bash.txt http://stackoverflow.com/questions/103944/ Note this means specific terminals will not have specific history! As such I do not like this. The normal method is to use "history -a; history -n" but this has proven un-reliable and flaky. Technique is to expand the 'new' history to the history file Then read the whole updated file back into the shells memory bhist() { builtin history "$@"; } history_update() { bhist -a; HISTFILESIZE=$HISTSIZE; bhist -c; bhist -r; } history() { history_update; bhist "$@"; } PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$';'} history_update" Alternative to PROMPT_COMMAND trap 'history_update' DEBUG The history() function ensures things are updated before uses look at history. Updating $HISTFILESIZE truncates the history as commands are appended. --- To keep terminals mostly separate, you can replace the above with just 'history -a' in the PROMPT_COMMAND. history_save() { history -a HISTFILESIZE=$HISTSIZE } history_reload() { history_save history -c history -r } history_edit() { history_save vim + "$HISTFILE" history -c history -r } PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$';'}history_save" hr() { history_reload; } he() { history_edit; } ------------------------------------------------------------------------------- Alternative merge during save (needs timestamps) ???? -------------------------------------------------------------------------------