Skip to content

Instantly share code, notes, and snippets.

@codemedic
Created May 14, 2025 14:16
Show Gist options
  • Save codemedic/b2cb583973f8dd3a291c56c1f5348efa to your computer and use it in GitHub Desktop.
Save codemedic/b2cb583973f8dd3a291c56c1f5348efa to your computer and use it in GitHub Desktop.
A helper for the Bash shell that allows you to manage individual history files for specific directories.

Change History

A helper for the Bash shell that allows you to manage individual history files for specific directories.

# The base path for the history files created by ch
ch_history_base_path="$HOME/.bash_history.d"
# ch_hist_file is a helper function to get the history file for a given directory.
# If no directory is given, it will use the current directory.
ch_hist_file() {
local dir
dir=$(realpath "${1:-.}")
# Check if the directory is under the home directory using a prefix match
if [[ "$dir" != "$HOME"* ]]; then
echo "ch: Directory is not under the home directory" 1>&2
return 1
fi
local history_file="${ch_history_base_path}/${dir#"$HOME"}.bash_history"
echo "$history_file"
}
# ch is a function to change the current directory and load the history file for that directory.
ch() {
# Check if we are already in a ch shell
if [[ "${__ch_load_history:-0}" == "1" ]]; then
echo "ch: Already in a ch shell" 1>&2
return 0
fi
local dir
dir=$(realpath "${1:-.}")
local history_file
if ! history_file="$(ch_hist_file "$dir")"; then
return 1
fi
echo "ch: Loading history file $history_file" 1>&2
# Make directory if it does not exist
mkdir -p "$(dirname "$history_file")"
# Create the history file if it does not exist
touch "$history_file"
# Set the history file for the new shell
export HISTFILE="$history_file"
# Set the history size for the new shell
export HISTSIZE=${HISTSIZE:-1000}
export HISTFILESIZE=${HISTFILESIZE:-2000}
# Open a new shell with the history file set to the current directory
# Use the --rcfile option to set the history file for the new shell.
exec bash --rcfile <(
echo ". ~/.bashrc"
echo "export HISTFILE='$history_file'"
echo "export HISTSIZE=$HISTSIZE"
echo "export HISTFILESIZE=$HISTFILESIZE"
echo "export __ch_load_history=1"
echo "builtin cd \"$dir\""
)
}
# ch_autoload is a helper function to check if the history file exists and run `ch` if it does.
ch_autoload() {
local history_file
if history_file="$(ch_hist_file)" && [[ -f "$history_file" ]]; then
ch .
fi
}
# auto_ch is a wrapper function for the builtin cd command that autoloads the history file. Intended to be used as an alias for cd.
auto_ch() {
# Run the builtin cd command first
builtin cd "$@" || return $?
# Autoload the history file if it exists
ch_autoload
}
alias cd=auto_ch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment