Create history log per working directory in bash

Building off the answer provided by Groggle, you can create an alternative cd (ch) in your ~/.bash_profile like.

function ch () {
    cd "$@"
    export HISTFILE="$(pwd)/.bash_history"
}

automatically exporting the new HISTFILE value each time ch is called.

The default behavior in bash only updates your history when you end a terminal session, so this alone will simply save the history to a .bash_history file in whichever folder you happen to end your session from. A solution is mentioned in this post and detailed on this page, allowing you to update your HISTFILE in realtime.

A complete solution consists of adding two more lines to your ~/.bash_profile,

shopt -s histappend
PROMPT_COMMAND="history -a;$PROMPT_COMMAND"

changing the history mode to append with the first line and then configuring the history command to run at each prompt.


You can set up code to be executed when changing directories. In zsh, this is as simple as defining a function and adding it to the chpwd_functions array. In bash this takes a little more work but you can do it as well; see Execute bash scripts on entering a directory for how to define a chpwd function that is executed on each directory change.

For what you want to do, the chpwd function needs to write the current history to the old file. To save the history to the right place when exiting bash, set the HISTFILE variable to the history file for the new directory, and read the new history.

chpwd () {
  history -a
  mkdir -p "$HOME/.bash_history.d/${PWD%/*}"
  HISTFILE=~/.bash_history.d/$PWD
  history -r
}

Note that I write the history to a hierarchy under your home directory, not to the current directory. Writing shell history to the current directory would be extremely dangerous and disruptive: you'd end up with privacy leaks all over the place, you'd risk modifying unintended files (what if the history file name is an existing symlink to some other place?), etc.

It would probably be better to write out the history after each command. In bash, you can enable this with the histappend option. With this option, you don't need to run history -a explicitly.

shopt -s histappend
chpwd () {
  mkdir -p "$HOME/.bash_history.d/${PWD%/*}"
  HISTFILE=~/.bash_history.d/$PWD
  history -r
}