19

I often find myself switching between Bash and Zsh, and using the history search functionality to recover a command.

However, since Bash and Zsh have different history files, I often find that the command I'm searching for has been executed in the other shell.

Is there any way to share or synchronize history between the two?

1
  • 4
    The syntax of bash and zsh is different enough that you'd end up with many commands that don't work when copied to the other shell. Sep 19, 2011 at 23:41

4 Answers 4

14

If you are using the defaults for bash and zsh:

$ cat ~/.histfile >> ~/.bash_history
$ youreditor ~/.zshrc
# Here change your config to:
HISTFILE=~/.bash_history
$ rm ~/.histfile

Now you have the same file for history in both shells.

7
  • 5
    Does this really work?? The two histfiles have completely different formats!
    – Neil Traft
    Jul 12, 2014 at 7:48
  • 1
    Yes, both shells use the same format. One command per line. Jul 13, 2014 at 18:32
  • 8
    My .zsh_history has lines like : 1399608924:0;hg diff whereas my .bash_history has simply hg diff. Maybe it's because I'm using oh-my-zsh?
    – Neil Traft
    Jul 14, 2014 at 23:58
  • 9
    you need to do unsetopt EXTENDED_HISTORY to get bash-compatible command-only history. Feb 2, 2016 at 22:54
  • 1
    zsh history for me is stored in ~/.zsh_history
    – Chris
    Feb 28, 2017 at 3:03
2

In response to Elad, people may have .bash_history files that have an extra line before each command that starts with (#) and has trailing digits following (123456789), for example: #123456789. If your bash_history file has these extra lines, use this modified version of Elad's code to process a clean zsh formatted history to use. Thanks Elad for the quick conversion code.

/*
 * You should backup your .bash_history file first doing this:
 * $ cp ~/.bash_history ~/.bash_history.backup
 * 
 * create the .js file to use first:
 * $ touch ~/.bash-history-to-zsh-history.js
 *
 * This is how I use it based on Elads example:
 * $ node ~/.bash-history-to-zsh-history.js >> ~/.zsh_history
 *
 **/

var fs = require("fs");
var a = fs.readFileSync(".bash_history");
var time = Date.now();
a.toString().split("\n").forEach(function(line){
  if (line.indexOf("#")!=0) console.log(": "+ (time++) + ":0;"+line);
});
1
  • then node bashtozsh.js | cat >> .zsh_history
    – Suhayb
    Jan 25 at 20:20
1

Not exactly what you were looking for, but in order to import from bash to zsh, you can use this node.js script:

// This is how I used it:
// $ node bash-history-to-zsh-history.js >> ~/.zsh_history

var fs = require("fs");
var a = fs.readFileSync(".bash_history");
var time = Date.now();
a.toString().split("\n").forEach(function(line){
  console.log(": "+ (time++) + ":0;"+line);
});

Source

0

Bash and zsh can share $HISTFILE

In zsh, I type bash to enter bash. Under my current setting, bash only save history after I press Ctrl+D (back to zsh)

The syntax of bash and zsh is different enough that you'd end up with many commands that don't work when copied to the other shell

For me, most commands work, but we should pay attention to the timestamp:
echo '14:56' is written to .zsh_history at 2022-01-11 14:57, when I press Ctrl+D)

With peco, I get the history:

^*_*^  > \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s{2}                                                                     Regexp [1987 (1/67)]
2022-01-11 14:57  e .zsh_history
2022-01-11 14:55  bash
2022-01-11 14:57  echo '14:56'
2022-01-11 14:57  echo  $HISTFILE
2022-01-11 14:57  print  $HISTFILE
2022-01-11 14:57  print -l $HISTFILE
2022-01-11 14:57  e .zsh_history
2022-01-11 14:57  ls
2022-01-11 14:55  history -i -n 1 | le
2022-01-11 14:55  ~
2022-01-11 14:55  -

In the .zsh_history

: 1641884226:0;ls
: 1641884234:17;e .zsh_history
print -l $HISTFILE
print  $HISTFILE
echo  $HISTFILE
echo '14:56'
: 1641884154:100;bash
: 1641884257:9;e .zsh_history
: 1641884338:0;e .zsh_history
: 1641880817:3534;e history_config_wf.zsh
: 1641884353:0;~

My setting with peco (in .zshrc):

BUFFER=$(history -i -2000 | eval $tac | cut -c 8- | peco --initial-filter="Regexp" --query "\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}\\s{2} $BUFFER") 

You must log in to answer this question.

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