Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|improve this question
    
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

2 Answers 2

up vote 0 down vote accepted

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.

share|improve this answer
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. –  Matthew Cline 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=$SHELL_SESSION_ID
    else
        export BASH_SESSION_ID="DEFAULT"
    fi
    .  ~/.bash_dirs
    load_dirs
fi

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:

_DIRS_DIRS=~/.dirs

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

_DIRS_FILE=$_DIRS_DIRS/$BASH_SESSION_ID

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
    fi

    # 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
        break
    done

    # 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
        fi
    done
}

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

_dirs_pushd()
{
    \pushd "$@"
    save_dirs
}
alias pushd=_dirs_pushd

_dirs_popd()
{
    \popd "$@"
    save_dirs
}
alias popd=_dirs_popd

# In case 'dirs -c' is used.
_dirs_dirs()
{
    \dirs "$@"
    save_dirs
}
alias dirs=_dirs_dirs
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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