# Pushd is the fastest navigational command you've never heard of

The pushd and popd commands are built-in features of the Bash shell to help you "bookmark" directories for quick navigation between locations on your hard drive.
You might already feel that the terminal is an impossibly fast way to navigate your computer: in just a few key presses, you can go any where on your hard drive, attached storage, or network share.
But that speed can break down when you find yourself going back and forth between directories, or when you get "lost" within your file system.
And those are precisely the problems **pushd** and **popd** aim to solve.

## pushd

At its most basic, ``pushd`` seems a lot like ``cd``.
It takes you from one directory to another.
Assume you have a directory called ``one``, which contains a subdirectory called ``two``, which contains a subdirectory called ``three``, and so on.
If your current working directory is ``one``, then you can move to ``two`` or ``three`` or anywhere with the ``cd`` command:

```
$ pwd
one
$ cd two/three
$ pwd
three
```

You can do the same with ``pushd``:

```
$ pwd
one
$ pushd two/three
~/one/two/three ~/one
$ pwd
three
```

The end result of ``pushd`` is the same as ``cd``, but there's an intermediate result: ``pushd`` echos your destination directory and your point of origin.
This is your *directory stack*, and it is what makes ``pushd`` so unique.


## Stacks

A stack, in computer terminology, refers to a collection of elements.
In the context of this command, the elements are directories you have recently visited by using the ``pushd`` command.
You can think of it as a history, or a map.

You can move all around your file system with ``pushd``, and each time you do, your previous and new location get added to the stack.

```
$ pushd four
~/one/two/three/four ~/one/two/three ~/one
$ pushd five
~/one/two/three/four/five ~/one/two/three/four ~/one/two/three ~/one
```

## Navigating the stack

Once you've built up a stack, you can use it as a collection of bookmarks or fast-travel waypoints.
For instance, assume that during a session you're doing a lot of work within the ``one/two/three/four/five`` directory structure of this example.
You know you've been to ``one`` recently, but you can't remember where in your ``pushd`` stack it's located now.
You can view your stack with the ``+0`` argument, which tells ``pushd`` not to change to any directory in your stack, but also prompts ``pushd`` to echo your current stack:

```
$ pushd +0
~/one/two/three/four ~/one/two/three ~/one ~/one/two/three/four/five
```

The first entry in your stack is your current location.
You can confirm that with ``pwd`` as usual:

```
$ pwd
~/one/two/three/four
```

Starting at 0, the second (2) element in your stack is ``~/one``, which is your desired destination.
You can move forward in your stack:

```
$ pushd +2
~/one ~/one/two/three/four/five ~/one/two/three/four ~/one/two/three
$ pwd
~/one
```

You can also move backward in your stack.
For instance, to quickly get to ``~/one/two/three`` given the example output, you can move back by one in your stack, keeping in mind that ``pushd`` starts with 0:

```
$ pushd -0
~/one/two/three ~/one ~/one/two/three/four/five ~/one/two/three/four
```

## Adding to the stack

You can continue to navigate your stack in this way and your stack remains a static listing of your commonly visited directories.
If you want to add a directory, just provide the path of the directory.

If it's a directory new to the stack, it's added to the list just as you'd expect:

```
$ pushd /tmp
/tmp ~/one/two/three ~/one ~/one/two/three/four/five ~/one/two/three/four
```

But if it already exists in the stack, it's added a second time.

```
$ pushd ~/one
~/one /tmp ~/one/two/three ~/one ~/one/two/three/four/five ~/one/two/three/four
```

While the stack is often used as a list of directories to which you want quick access, it is actually a true history of where you've been.
If you don't want a directory added reduntantly to the stack, you must use the ``+N`` and ``-N`` notation.


## Removing directories from the stack

Your stack is, obviously, not immutable.
You can add to it with ``pushd`` and you can remove items from it with ``popd``.

For instance, assume you have just used ``pushd`` to add ``~/one`` to your stack, making ``~/one`` your current working directory.
To remove the first (or "zeroeth", if you prefer) element:

```
$ pwd
~/one
$ popd +0
/tmp ~/one/two/three ~/one ~/one/two/three/four/five ~/one/two/three/four
$ pwd
~/one
```

Of course, you can remove any element, starting your count at 0.

```
$ pwd ~/one
$ popd +2
/tmp ~/one/two/three ~/one/two/three/four/five ~/one/two/three/four
$ pwd ~/one
```

You can also use ``popd`` from the back of your stack, again starting with 0.
For example, to remove the final directory from your stack:

```
$ popd -0
/tmp ~/one/two/three ~/one/two/three/four/five
```

When used in this way, ``popd`` does not change your working directory.
It only manipulates your stack.


## Navigating with popd

The default behaviour of ``popd``, given no arguments, is to remove the first (zeroeth) item from your stack, and to make the next item your current working directory.

This is most useful as a quick change command, when you are, for instance, working in two different directories and just need to duck away for a moment to some other location.
You don't have to think about your directory stack if you don't need an elaborate history:

```
$ pwd
~/one
$ pushd ~/one/two/three/four/five
$ popd
$ pwd
~/one
```

It's also not required that you use ``pushd`` and ``popd`` in rapid succession.
If you use ``pushd`` to visit a different location and then get distracted for three hours chasing down a bug or doing research, you'll find your directory stack patiently waiting (unless you've ended your terminal session).

```
$ pwd ~/one
$ pushd /tmp
$ cd {/etc,/var,/usr}; sleep 2001
[...]
$ popd
$ pwd
~/one
```

## Pushd and popd in the real world

The ``pushd`` and ``popd`` commands are surprisingly useful.
Once you learn them, you'll find excuses to put them to good use, and you'll get familiar with the concept of the directory stack.
Getting comfortable with ``pushd`` was what helped me understand the ``git stash``, which is entirely unrelated to ``pushd`` but similar in conceptual intangibility.

Using ``pushd`` and ``popd`` in shell scripts can be tempting, but generally it's arguably best to avoid them.
They aren't portable outside of Bash and Zsh, and they can be obtuse when re-reading a script (``pushd +3`` is less clear than ``cd $HOME/$DIR/$TMP`` or similar).

Aside from these warnings, if you're a regular Bash or Zsh user, then you can and should try ``pushd`` and ``popd``.