Working efficient within different directories in a Linux Shell

TOC

Lets Suppose you need to perform a certain kind of work in all of these directories: 

  • /var/www/html
  • /etc/apache2
  • /etc/ssl/certs
  • ~/Work/Projects/Web/src

You might know about the "cd" command. But isn't it annoying if you need to use and retype a lot of Commands, like for example:

$ cd ~/Work/Projects/Web/src
$ cd /var/www/html
$ cd /etc/apache2
$ cd ~/Work/Projects/Web/src
$ cd /etc/ssl/certs

But there is a much better and more efficient way. Take advantage of a shell feature called a directory stack.

Directory stack

You can manipulate the stack by performing two operations called pushing and popping.

  • Pushing a  directory adds it to the beginning of the list, which is traditionally called the top of the stack.
  • Popping removes the topmost directory from the stack.
  • Initially, the stack contains only your current directory, but you can add (push) and remove (pop) directories and rapidly cd among them.

Push a directory onto the stack

The command pushd (short for “push directory”) does all of the following:

  1. Adds a given directory to the top of the stack
  2. Performs a cd to that directory
  3. Prints the stack from top to bottom for your reference

Let's build a directory stack of four directories, pushing them onto the stack one at a time:

$ pwd
/home/john/Work/Projects/Web/src
$ pushd /var/www/html
/var/www/html ~/Work/Projects/Web/src
$ pushd /etc/apache2
/etc/apache2 /var/www/html ~/Work/Projects/Web/src
$ pushd /etc/ssl/certs
/etc/ssl/certs /etc/apache2 /var/www/html
~/Work/Projects/Web/src
$ pwd
/etc/ssl/certs

The shell prints the stack after each pushd operation. The current directory is the leftmost (top) directory.

View a directory stack

Print a shell’s directory stack with the dirs command. It does not modify the stack:

$ dirs -p
/etc/ssl/certs
/etc/apache2
/var/www/html
~/Work/Projects/Web/src

you can leave out the -p if you don't want to have each of them at it's own line. Or you can pass a -v to see them numbered:

$ dirs -v
0 /etc/ssl/certs
1 /etc/apache2
2 /var/www/html
3 ~/Work/Projects/Web/src

Pop a directory from the stack

The popd command (“pop directory”) is the reverse of pushd. It does all of the following:

  1. Removes one directory from the top of the stack
  2. Performs a cd to the new top directory
  3. Prints the stack from top to bottom for your reference

For example, if your stack has four directories:

$ dirs
/etc/ssl/certs /etc/apache2 /var/www/html
~/Work/Projects/Web/src

then repeatedly running popd will traverse these directories from top to bottom:

$ popd
/etc/apache2 /var/www/html ~/Work/Projects/Web/src
$ popd
/var/www/html ~/Work/Projects/Web/src
$ popd
~/Work/Projects/Web/src
$ popd
bash: popd: directory stack empty
$ pwd
~/Work/Projects/Web/src

Swap directories on the stack

Now that you can build and empty the directory stack, let’s focus on practical use cases. pushd with no arguments swaps the top two directories in the stack and navigates to the new top directory. Let’s jump between /etc/apache2 and your work directory several times by simply running pushd. See how the third directory /var/www/html remains in the stack as the first two directories swap positions:

$ dirs
/etc/apache2 ~/Work/Projects/Web/src /var/www/html
$ pushd
~/Work/Projects/Web/src /etc/apache2 /var/www/html
$ pushd
/etc/apache2 ~/Work/Projects/Web/src /var/www/html
$ pushd
~/Work/Projects/Web/src /etc/apache2 /var/www/html

pushd behaves similarly to the cd - command, toggling between two directories, but it does not have the limitation of remembering just one directory.

Turn a mistaken cd into a pushd

Suppose you are jumping among several directories with pushd and you accidentally run cd instead and lose a directory:

$ dirs
~/Work/Projects/Web/src /var/www/html /etc/apache2
$ cd /etc/ssl/certs
$ dirs
/etc/ssl/certs /var/www/html /etc/apache2

Oops, the accidental cd command replaced ~/Work/Projects/Web/src in the stack with /etc/ssl/certs. But don’t worry. You can add the missing directory back to the stack without typing its long path. Just run pushd twice, once with a dash argument and once without:

$ pushd -
~/Work/Projects/Web/src /etc/ssl/certs /var/www/html
/etc/apache2
$ pushd
/etc/ssl/certs ~/Work/Projects/Web/src /var/www/html
/etc/apache2

Why this works:

  • The first pushd returns to your shell’s previous directory, ~/Work/Projects/Web/src, and pushes it onto the stack. pushd, like cd, accepts a dash as an argument to mean “go back to my previous directory.”
  • The second pushd command swaps the top two directories, bringing you back to /etc/ssl/certs. The end result is that you’ve restored ~/Work/Projects/Web/src to the second position in the stack, exactly where it would have been if you hadn’t made your mistake.

Go deeper into the stack

What if you want to cd between directories in the stack other than the top two? pushd and popd accept a positive or negative integer argument to operate further into the stack. The command:

$ pushd +N

shifts N directories from the top of the stack to the bottom and then performs a cd to the new top directory. A negative argument (-N) shifts directories in the opposite direction, from the bottom to the top, before performing the cd.

$ dirs
/etc/ssl/certs ~/Work/Projects/Web/src /var/www/html
/etc/apache2
$ pushd +1
~/Work/Projects/Web/src /var/www/html /etc/apache2
/etc/ssl/certs
$ pushd +2
/etc/apache2 /etc/ssl/certs ~/Work/Projects/Web/src
/var/www/html

In this manner, you can jump to any other directory in the stack with a simple command. If your stack is long, however, it may be difficult to judge a directory’s numeric position by eye. So, print the numeric position of each directory with dirs -v, as you did in “View a
directory stack”:

$ dirs -v
0 /etc/apache2
1 /etc/ssl/certs
2 ~/Work/Projects/Web/src
3 /var/www/html

To shift /var/www/html to the top of the stack (and make it your current directory), run pushd +3. To jump to the directory at the bottom of the stack, run pushd -0 (dash zero):

$ dirs
/etc/apache2 /etc/ssl/certs ~/Work/Projects/Web/src
/var/www/html
$ pushd -0
/var/www/html /etc/apache2 /etc/ssl/certs
~/Work/Projects/Web/src

You also can remove directories from the stack beyond the top directory, using popd with a numeric argument. The command:

$ popd +N

removes the directory in position N from the stack, counting down from the top. A negative argument (-N) counts up from the bottom of the stack instead. Counting begins at zero, so popd +1 removes the second directory from the top:

$ dirs
/var/www/html /etc/apache2 /etc/ssl/certs
~/Work/Projects/Web/src
$ popd +1
/var/www/html /etc/ssl/certs ~/Work/Projects/Web/src
$ popd +2
/var/www/html /etc/ssl/certs