Do we have more history for cd?

16,336

Solution 1

The command you are looking for is pushd and popd.

You could view a practical working example of pushd and popd from here.

mkdir /tmp/dir1
mkdir /tmp/dir2
mkdir /tmp/dir3
mkdir /tmp/dir4

cd /tmp/dir1
pushd .

cd /tmp/dir2
pushd .

cd /tmp/dir3
pushd .

cd /tmp/dir4
pushd .

dirs
/tmp/dir4 /tmp/dir4 /tmp/dir3 /tmp/dir2 /tmp/dir1

Solution 2

You didn't specify which shell you are using, so let this be excuse to advertise zsh.

Yes, we do have more history for cd, namely cd -2, cd -4 etc. Very convenient is cd -TAB, especially with completion system and colors enabled:

This is what I have in .zshrc:

setopt AUTO_PUSHD                  # pushes the old directory onto the stack
setopt PUSHD_MINUS                 # exchange the meanings of '+' and '-'
setopt CDABLE_VARS                 # expand the expression (allows 'cd -2/tmp')
autoload -U compinit && compinit   # load + start completion
zstyle ':completion:*:directory-stack' list-colors '=(#b) #([0-9]#)*( *)==95=38;5;12'

And the result:

enter image description here

Solution 3

To answer your question regarding "more history". No the cd - feature in Bash only supports a single directory that you can "flip" back to. As @Ramesh states in his answer. If you want a longer history of directories you can use pushd and popd to save a directory or return to a previous one.

You can also see the list of what's currently in the stack with the dirs command.

A detailed explanation can be found from this answer titled: How do I use pushd and popd commands?.

Solution 4

You have as much history as you want:

cd() {
[ "$((${DIRSTACKMAX##*[!0-9]*}0/10))" -gt 0 ] &&
        set -- "$@" "$DIRSTACK"               &&
        DIRSTACK='pwd -P >&3; command cd'     ||
        { command cd "$@"; return; }
_q()    while   case "$1" in (*\'*) :   ;;      (*)
                ! DIRSTACK="$DIRSTACK '$2$1'"   ;;esac
        do      set -- "${1#*\'}" "$2${1%%\'*}'\''"
        done
while   [ "$#" -gt 1 ]
do      case    ${1:---} in (-|[!-]*|-*[!0-9]*) : ;;
        (*)     eval "  set $((${1#-}+1))"' "${'"$#}\""
                eval '  set -- "$2"'" $2"'
                        set -- "${'"$1"'}" "$1"'
        ;;esac; _q "$1"; shift
done
eval "  DIRSTACK=; $DIRSTACK    &&"'
        _q "$OLDPWD"            &&
        DIRSTACK=$DIRSTACK\ $1
        set "$?" "${DIRSTACK:=$1}"'" $1
"       3>/dev/null
[ "$(($#-1))" -gt "$DIRSTACKMAX" ] &&
        DIRSTACK="${DIRSTACK% \'/*}"
unset -f _q; return "$1"
}

That's a shell function that should enable any POSIX compatible shell to offer zsh-style cd history. It does all of its work without invoking a single subshell, and I believe its flow is pretty sound - it seems to handle all cases correctly under moderate testing.

The function attempts to play as nicely with its environment as it may while still relying on fully portable syntax - it makes only one assumption and that is that the $DIRSTACK environment variable is its property to do with as it will.

It canonicalizes all paths that it stores in $DIRSTACK and serializes all of them on single-quotes - though it ensures each is safely quoted and serialized before adding it to the value of the variable and shouldn't have any issue with any special characters of any kind. If the $DIRSTACKMAX environment variable is set it will use it as an upper limit for the number of paths it retains in history, else the limit is one.

If you load the function you just cd as normal but will also be able to do the cd -[num] for retracing back through your change directory history.

The function's primary mechanism is cd itself - and the ${OLD,}PWD environment variables. POSIX specifies that cd change these for every path move - and so this just uses the shell's builtin variables and saves the values for as long as you like.

Solution 5

You can install and use my dirhistory utility for bash.

Basically, it's a daemon that collects directory changes from all your shells, and a Cdk program that displays the history and lets you pick any directory to switch to (so you're not limited to a stack).

Share:
16,336

Related videos on Youtube

Tim
Author by

Tim

Elitists are oppressive, anti-intellectual, ultra-conservative, and cancerous to the society, environment, and humanity. Please help make Stack Exchange a better place. Expose elite supremacy, elitist brutality, and moderation injustice to https://stackoverflow.com/contact (complicit community managers), in comments, to meta, outside Stack Exchange, and by legal actions. Push back and don't let them normalize their behaviors. Changes always happen from the bottom up. Thank you very much! Just a curious self learner. Almost always upvote replies. Thanks for enlightenment! Meanwhile, Corruption and abuses have been rampantly coming from elitists. Supportive comments have been removed and attacks are kept to control the direction of discourse. Outright vicious comments have been removed only to conceal atrocities. Systematic discrimination has been made into policies. Countless users have been harassed, persecuted, and suffocated. Q&A sites are for everyone to learn and grow, not for elitists to indulge abusive oppression, and cover up for each other. https://softwareengineering.stackexchange.com/posts/419086/revisions https://math.meta.stackexchange.com/q/32539/ (https://i.stack.imgur.com/4knYh.png) and https://math.meta.stackexchange.com/q/32548/ (https://i.stack.imgur.com/9gaZ2.png) https://meta.stackexchange.com/posts/353417/timeline (The moderators defended continuous harassment comments showing no reading and understanding of my post) https://cs.stackexchange.com/posts/125651/timeline (a PLT academic had trouble with the books I am reading and disparaged my self learning posts, and a moderator with long abusive history added more insults.) https://stackoverflow.com/posts/61679659/revisions (homework libels) Much more that have happened.

Updated on September 18, 2022

Comments

  • Tim
    Tim almost 2 years

    cd - can move to the last visited directory. Can we visit more history other than the last one?

  • Ramesh
    Ramesh over 9 years
    I have included a reference from your answer. Hope you don't mind. :)
  • jimmij
    jimmij over 9 years
    OK, I won't delete this answer, maybe will be useful for others.
  • yieldsfalsehood
    yieldsfalsehood over 9 years
    Unless the question specifically asks about bash, this is a valid answer. Don't remove it.
  • mechalynx
    mechalynx over 9 years
    There's also $OLDPWD in case you want to flip back and forth between two directories using the same command, but I'm unsure how shell-specific and distribution/kernel-specific this is.
  • Ooker
    Ooker over 9 years
    What if the OP edits his question to include bash only, will this answer still be valid?
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 9 years
    @ivy_lynx OLDPWD exists in all POSIX shells, but it's useless for this question which asks how to go beyond that (the question already mentions cd - which is a shortcut for cd "$OLDPWD").
  • alexis
    alexis over 9 years
    Nice feature, didn't know this about zsh.
  • Dave Rayner
    Dave Rayner over 9 years
    @Ooker that's discussed in detail somewhere on meta.SO or meta.SE, but in this case I would say yes because it's still very useful, and even worthwhile to say "this feature could be implemented because it exists here."
  • GnP
    GnP over 9 years
    Is there a reason you use cd /tmp/dir1; pushd . instead of just pushd /tmp/dir1?
  • Ramesh
    Ramesh over 9 years
    @gnp, no specific reason. It was just taken from the link that I have referred to in the answer. pushd /tmp/dir1 should work just fine.
  • GnP
    GnP over 9 years
    Ok, just picked my curiosity. I'd like to suggest you improve your answer with an actual example using pushd and popd to traverse a directory tree back and forth. Your answer is already the correct one.
  • wjv
    wjv about 8 years
    It might bear mentioning that apart from setopt AUTO_PUSHD, none of the above setup is required to get an omnipresent directory stack with completion in stock zsh. PUSHD_MINUS reverses the sense of cd + and cd - (a matter of taste), CDABLE_VARS is irrelevant to directory stacks, and the zstyle invocation given here simply adds colouring to the output of a directory stack completion. One must however initialise the completion subsystem with autoload -U compinit && compinit.
  • mikeserv
    mikeserv over 7 years
    @datUser - i knew someone had a dat. youre quite welcome
  • ddnomad
    ddnomad about 7 years
    Hm, looks promising. I'll check it out.
  • jo_
    jo_ about 7 years
  • rmbianchi
    rmbianchi over 3 years
    Great! I didn't know about this specific feature of zsh! Thanks a lot for the hint! +1