Bash will remember command history across sessions, but not the directory stack created with pushd. Is there any way to remember the directory stack as well?

  • Thanks for sharing your solution, but please post it as an answer and not in your original question.
    – mpy
    Jun 27 '13 at 8:19

How about using the dirs -p output?
You could save it from your .bash_logout and sort-of re-load it with a minor script in the .bash_login

See more at Directory Stack Builtins bash page.

  • 1
    I'd initially dismissed that idea, since if bash terminates abnormally, or if bash isn't a login shell, then that won't work. But I could alias pushd and popd to dump dirs -p to a file on each use. Jun 17 '13 at 21:19

I finally found a way to determine which shell I'm in consistently across sessions: the environmental variable SHELL_SESSION_ID, which the KDE session manager supports for Konsole (not sure about other desktop environments). With that said, the solution I put together based on user nik's answer:

In .bashrc, in the setup code for interactive shells, I added this:

# Don't remember directory stacks for subshells, just the top level
# shell.
if [[ -z "$BASH_SESSION_ID" ]]; then
    # Get bash-session the X Windows session manager, if possible.
    if [[ -n "$SHELL_SESSION_ID" ]]; then
        export BASH_SESSION_ID="DEFAULT"
    .  ~/.bash_dirs

BASH_SESSION_ID is used rather than directly using SHELL_SESSION_ID so that for environments that don't have SHELL_SESSION_ID, something else can be used.

The contents of .bash_dirs is this:


# Silently make sure ~/.dirs exists
\mkdir -p $_DIRS_DIRS


save_dirs() {
    \dirs -l -p > $_DIRS_FILE

load_dirs() {
    # Start out with a fresh directory stack.
    \dirs -c

    # Make sure there's at least an empty file.
    if [[ ! -f "$_DIRS_FILE" ]]; then
        touch $_DIRS_FILE

    # Start out in the directory we left off at
    for dir in $(cat $_DIRS_FILE) ; do
        \cd $dir  > /dev/null 2>&1

        # Just need the first line

    # Restore saved dir stack in reverse order.
    for dir in $(cat $_DIRS_FILE | tac) ; do
        # But don't duplicate the directory we left off at
        if [[ $PWD != $dir ]]; then
            \pushd -n $dir > /dev/null 2>&1

# NOTE: aliases can't take parameters, so we have to alias to functions.

    \pushd "$@"
alias pushd=_dirs_pushd

    \popd "$@"
alias popd=_dirs_popd

# In case 'dirs -c' is used.
    \dirs "$@"
alias dirs=_dirs_dirs
  • Raw pastebin of the above .bash_dirs for command line download: pastebin.com/raw/FsAcG23N Feb 13 '16 at 20:36
  • For anyone wondering about the leading backslash ("\") on many of the commands above: it disregards any possible aliases and just executes the default command of that name.
    – Edward
    Apr 2 '19 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.