5

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)

7
  • 1
    Why not use pwd to figure out where you are?
    – phemmer
    Feb 21, 2012 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, 2012 at 12:46
  • 1
    Do you know zsh? It has really nice features like AUTO_PUSHD.
    – jofel
    Feb 21, 2012 at 14:39
  • 3
    +1 Thank you for teaching me about cd -! For most of a decade, I've been doing $ cd $OLDPWD instead. Feb 21, 2012 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.
    – phemmer
    Feb 22, 2012 at 1:58

3 Answers 3

7

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.

3
  • 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, 2012 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, 2012 at 12:53
  • You might also want to unset old and current after you're done with them.
    – Wildcard
    Mar 29, 2016 at 23:08
3

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.

0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .