4

There is a similar question here, but I want to achieve something different: I would like to share history between sessions, but without mixing the commands that were executed in different sessions together.

For example, let's say I have two shell sessions: A and B. I type some commands in A:

A$ ls ~
A$ ls /etc

And in B:

B$ git status
B$ git log

When I type history in a shell, I'd like to see all commands from this shell together, after commands from other shells - so that I can always use uparrrow to get last commands from the current shell. In other words, history in shell A should show

git status
git log
ls ~
ls /etc

And in shell B it should show

ls ~
ls /etc
git status
git log

How to do this?

1
  • 1
    You do know that for long session, that can mean 'newer' commands from on session many become lost more quickly than older commands from another session.
    – anthony
    Oct 9, 2020 at 4:18

2 Answers 2

6

Seems there is no built-in solution for this, but it turned out implementing it manually is not that difficult. One has to store history of each session separately and recreate it on every prompt (it's not as slow as it may sound). Here's the core logic:

# on every prompt, save new history to dedicated file and recreate full history
# by reading all files, always keeping history from current session on top.
update_history () {
  history -a ${HISTFILE}.$$
  history -c
  history -r
  for f in `ls ${HISTFILE}.[0-9]* | grep -v "${HISTFILE}.$$\$"`; do
    history -r $f
  done
  history -r "${HISTFILE}.$$"
}
export PROMPT_COMMAND='update_history'

# merge session history into main history file on bash exit
merge_session_history () {
  cat ${HISTFILE}.$$ >> $HISTFILE
  rm ${HISTFILE}.$$
}
trap merge_session_history EXIT

See this gist for a full solution, including some safeguards and performance optimizations.

0

This is not exactly an answer to the question, but still very similar, so some people might find it interesting:

My intuition is that uparrow should act on the local history, but Ctrl-r should act on a global, shared history. Here is one way to do it (using fzf):

# do not overwrite the history file on exit
shopt -s histappend

# immediately add the last command to the history file
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"

# use a custom function that uses $HISTFILE for Ctrl-r
__my_history__() {
    READLINE_LINE=$(fzf --query "$READLINE_LINE" < $HISTFILE)
    READLINE_POINT=${#READLINE_LINE}
}
bind -x '"\C-r": __my_history__'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .