I am a happy user of the cd - command to go to the previous directory. At the same time I like pushd . and popd.

However, when I want to remember the current working directory by means of pushd ., I lose the possibility to go to the previous directory by cd -. (As pushd . also performs cd .).

How can I use pushd to still be able to use cd -

By the way: GNU bash, version 4.1.7(1)

  • 1
    Why not use pwd to figure out where you are? – Patrick Feb 21 '12 at 12:39
  • I don't understand your question? The point is that pushd breaks the behavior of cd - that I want (or expect). I know perfectly well in which directory I am, but I want to increase the speed with which I change directories :) – Bernhard Feb 21 '12 at 12:46
  • 1
    Do you know zsh? It has really nice features like AUTO_PUSHD. – jofel Feb 21 '12 at 14:39
  • 3
    +1 Thank you for teaching me about cd -! For most of a decade, I've been doing $ cd $OLDPWD instead. – Theodore R. Smith Feb 21 '12 at 16:26
  • 1
    @bernhard Oh, I misunderstood what you were asking. You were wanting to know how to store the current working directory. I was interpreting it as you wanted to remember (as in you forgot) your current working directory. – Patrick Feb 22 '12 at 1:58
up vote 7 down vote accepted

You can use something like this:

push() { 
    if [ "$1" = . ]; then
        old=$OLDPWD
        current=$PWD
        builtin pushd .
        cd "$old"
        cd "$current"
    else
        builtin pushd "$1"
    fi
}

If you name it pushd, then it will have precedence over the built-in as functions are evaluated before built-ins.

You need variables old and current as overwriting OLDPWD will make it lose its special meaning.

  • This works perfectly for me. Is there no such feature in the built-in pushd? As I would always prefer a standard solution. Thanks for this function however, maybe I will leave out the argument and it's checking at some point. – Bernhard Feb 21 '12 at 12:41
  • There is no such feature in the builtin. Your own function is the best solution because pushd and popd both call cd modifying $OLDPWD, hence the source of your problem. I would name the function saved and use it in the context you like too, that of saving cwd. – bsd Feb 21 '12 at 12:53
  • You might also want to unset old and current after you're done with them. – Wildcard Mar 29 '16 at 23:08

A slightly more concise version of Wojtek's answer:

pushd () {
        if [ "$1" = . ]; then
                cd -
                builtin pushd -
        else    
                builtin pushd "$1"
        fi      
}

By naming the function pushd, you can use pushd as normal, you don't need to remember to use the function name.

Kevin's answer is excellent. I've written up some details about what's going on, in case people are looking for a better understanding of why their script is necessary to solve the problem.

The reason that pushd . breaks the behavior of cd - will be apparent if we dig into the workings of cd and the directory stack. Let's push a few directories onto the stack:

$ mkdir dir1 dir2 dir3
$ pushd dir1
~/dir1 ~
$ pushd../dir2
~/dir2 ~/dir1 ~
$ pushd../dir3
~/dir3 ~/dir2 ~/dir1 ~
$ dirs -v
0       ~/dir3
1       ~/dir2
2       ~/dir1
3       ~

Now we can try cd - to jump back a directory:

$ cd -
/home/username/dir2
$ dirs -v
0       ~/dir2
1       ~/dir2
2       ~/dir1
3       ~

We can see that cd - jumped us back to the previous directory, replacing stack ~0 with the directory we jumped into. We can jump back with cd - again:

$ cd -
/home/username/dir3
$ dirs -v
0       ~/dir3
1       ~/dir2
2       ~/dir1
3       ~

Notice that we jumped back to our previous directory, even though the previous directory wasn't actually listed in the directory stack. This is because cd uses the environment variable $OLDPWD to keep track of the previous directory:

$ echo $OLDPWD
/home/username/dir2 

If we do pushd . we will push an extra copy of the current directory onto the stack:

$ pushd . 
~/dir3 ~/dir3 ~/dir2 ~/dir1 ~
$ dirs -v
0       ~/dir3
1       ~/dir3
2       ~/dir2
3       ~/dir1
4       ~

In addition to making an extra copy of the current directory in the stack, pushd . has updated $OLDPWD:

$echo $OLDPWD
/home/username/dir3

So cd - has lost its useful history, and will now just move you to the current directory - accomplishing nothing.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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