477

What are the practical uses of both pushd and popd when there is an advantage of using these two commands over cd and cd -?

EDIT: I'm looking for some practical examples of uses for both of these commands or reasons for keeping stack with directories (when you have tab completion, cd -, aliases for shortening cd .., etc.).

syntagma
  • 12,311

11 Answers11

432

pushd, popd, and dirs are shell builtins which allow you manipulate the directory stack. This can be used to change directories but return to the directory from which you came.

For example

start up with the following directories:

$ pwd
/home/saml/somedir
$ ls
dir1  dir2  dir3

pushd to dir1

$ pushd dir1
~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir1 ~/somedir

dirs command confirms that we have 2 directories on the stack now. dir1 and the original dir, somedir. NOTE: Our "current" directory is ~/somedir/dir1.

pushd to ../dir3 (because we're inside dir1 now)

$ pushd ../dir3
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ dirs
~/somedir/dir3 ~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir3

dirs shows we have 3 directories in the stack now. dir3, dir1, and somedir. Notice the direction. Every new directory is getting added to the left. When we start popping directories off, they'll come from the left as well.

manually change directories to ../dir2

$ cd ../dir2
$ pwd
/home/saml/somedir/dir2
$ dirs
~/somedir/dir2 ~/somedir/dir1 ~/somedir

Now start popping directories

$ popd
~/somedir/dir1 ~/somedir
$ pwd
/home/saml/somedir/dir1

Notice we popped back to dir1.

Pop again...

$ popd
~/somedir    
$ pwd
/home/saml/somedir

And we're back where we started, somedir.

Might get a little confusing, but the head of the stack is the directory that you're currently in. Hence when we get back to somedir, even though dirs shows this:

$ dirs
~/somedir

Our stack is in fact empty.

$ popd
bash: popd: directory stack empty
AdminBee
  • 22,803
slm
  • 369,824
  • 33
    Thanks, I totally understand the concept of stack and how this commands work. However, I'm looking for some practical reasons for keeping stack with directories (when you have tab completion, cd -, aliases for shortening cd .., etc.). – syntagma May 25 '13 at 18:26
  • 35
    I often use pushd & popd in scripts b/c they save me from having to remember where I was coming from, I can always just popd to get back from where I came. I usually do popd >/dev/null 2>&1 to make it silent. I use cd- everyday in my shell. There are some other time saving tips in this article as well: http://www.thegeekstuff.com/2008/10/6-awesome-linux-cd-command-hacks-productivity-tip3-for-geeks/. – slm May 25 '13 at 18:31
  • Take a look at $CDPATH. It's pretty powerful if you're looking for more efficient ways to get around via cd. – slm May 25 '13 at 18:38
  • 1
    @slm, is there any advantage to using popd >/dev/null 2>&1 in a script rather than cd - >/dev/null 2>&1? – Garrett Aug 22 '14 at 00:59
  • 2
    @Garrett - none that I can conceive. – slm Aug 22 '14 at 01:11
  • 9
    @Garrett @slm since cd - only tracks the last directory, i imagine it would be possible to have issues if you call a function which also changes directory internally. in that case, the function would end up resetting - to your current directory, not the directory you want to pop back to. pushd/popd is the safest method. Note: i haven't tested my theory. – Binary Phile Nov 10 '14 at 20:52
  • 6
    Why not going back to ~/somedir/dir3 after the first popd? – Ziyuan Feb 18 '16 at 22:03
  • @BinaryPhile wouldn't you have the same issue then if this hypothetical function you called also modified the directory stack? – Philip Schiff Feb 24 '19 at 12:44
  • Can I also jumpd to a dir on the stack by index or something ? – TheEagle Feb 24 '24 at 20:41
  • What is the purpose of the manually change directories to ../dir2 section? - anyway valuable explanation – Manuel Jordan Feb 25 '24 at 23:54
260

There is a really useful use case for pushd and popdcommands for working with several folders simultaneously.

You can navigate the stack very easily, since it is enumerated. Meaning, you can have several working folders at your disposal during work.

See a simple example below.


First, let's create example folder structure.

    user@vb:~$ mkdir navigate
    user@vb:~/navigate$ mkdir dir1
    user@vb:~/navigate$ mkdir dir2
    user@vb:~/navigate$ mkdir dir3

Then you can add all your folders to the stack:

    user@vb:~/navigate$ pushd dir1/
    ~/navigate/dir1 ~/navigate
    user@vb:~/navigate/dir1$ pushd ../dir2/
    ~/navigate/dir2 ~/navigate/dir1 ~/navigate
    user@vb:~/navigate/dir2$ pushd ../dir3/
    ~/navigate/dir3 ~/navigate/dir2 ~/navigate/dir1 ~/navigate

You can look it up by:

    user@vb:~/navigate/dir3$ dirs -v
     0  ~/navigate/dir3
     1  ~/navigate/dir2
     2  ~/navigate/dir1
     3  ~/navigate

To navigate safely, you need to add the last (zero) folder twice, since it will be always rewritten:

    user@vb:~/navigate/dir3$ pushd .
    user@vb:~/navigate/dir3$ dirs -v
     0  ~/navigate/dir3
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate

Now, you can jump around through these folders and work with stack as with aliases for the folders. I guess the following part is self explanatory:

    user@vb:~/navigate/dir3$ cd ~4
    user@vb:~/navigate$ dirs -v
     0  ~/navigate
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
    user@vb:~/navigate$ cd ~3
    user@vb:~/navigate/dir1$ dirs -v
     0  ~/navigate/dir1
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate
    user@vb:~/navigate/dir1$ touch text.txt
    user@vb:~/navigate/dir1$ cp text.txt ~2
    user@vb:~/navigate/dir1$ ls ~2
    text.txt
    user@vb:~/navigate/dir1$ dirs -v
     0  ~/navigate/dir1
     1  ~/navigate/dir3
     2  ~/navigate/dir2
     3  ~/navigate/dir1
     4  ~/navigate

Additional tip is to create some alias for dirs -v.

For example:

# In ~/.bashrc
alias dirs="dirs -v"
hoijui
  • 731
Jun Murakami
  • 2,701
62

One simple use case for using dirs stack what you cannot do by just cd is:

pushd . adds current directory XX to dirs stack. Afterwards, you can move around using cd, and to return to XX you just do popd regardless of how "far away" are you in the directory tree (can jump over multiple levels, sideways etc). Especially useful in bash scripts.

  • 8
    I think this is the feature I take advantage of most often. Because pushd/popd work independent from cd, you can use them as a more stable bookmark than cd -. – Gordon Bean Aug 17 '16 at 15:31
  • for me this is not true. Every time i use cd my stack changes. – Harendra Singh Apr 04 '17 at 04:48
  • 2
    oh that was coz of using zsh, when I change to bash, it works fine – Harendra Singh Apr 04 '17 at 05:07
  • 7
    This is the only substantive answer as regards a comparison with cd -, IMO. As to whether pushd foo; ; popd is more worthwhile than a=foo; cd $a; ; cd $a ... For scripts I can see a tiny syntactic convenience in the former (pushd), but a massive improvement in clarity in the latter ([explicit] variables!). For an interactive session, I think I would just assume have my directory hierarchy organized properly in the first place, and if I got lost simply cd ~/back/to/obvious/path. – Jan Kyu Peblik Jun 15 '17 at 18:27
  • 3
    @HarendraSingh you don't happen to have AUTO_PUSHD set? It will make cd behave like pushd, unset it and you'll be back to "normal behaviour". – Magnus Dec 25 '19 at 09:28
  • For those using prezto for zsh, the 'directory' module sets AUTO_PUSHD, sneakily. You can comment that out here: ~/.zprezto/modules/directory/init.zsh – ijoseph Sep 04 '21 at 02:31
19

The pushd/popd is such a simple concept which took me awhile to comprehend since people tend to teach it by defining these commands as commands that 'manipulate the directory stack' which in my opinion is very confusing.

I look at it in a different way:

pushd [folder_name] - will cd into [folder_name] and will document the destination which is [folder_name] in a dir-stack. While the top directory in the stack will always be the current dir you are in.

popd - will cd into the directory record which is documented at the top of the stack and then remove the documentation (from the dir-stack).

dirs - Will print the dir-stack (which can be treated as the dir Db where the leftmost entry is the current directory (top of the stack).

So the 2 most popular use cases are:

Use case 1: Navigating using pushd and popd

root@mypc:/main/$ ls
dir1  dir2  dir3  dir4

root@mypc:/main/$ dirs # prints the current stack /main

root@mypc:/main/$ pushd dir1 # Will cd to dir1 and document dir1 in dir stack, stack is now: /main/dir1 /main root@mypc:/main/dir1$ # I am now in /main/dir1

root@mypc:/main/dir1$ # Now let's go wild and document whatever I want root@mypc:/main/dir1$ pushd ../dir2 root@mypc:/main/dir2$ # Woo I am in /main/dir2 root@mypc:/main/dir2$ pushd ../dir3 root@mypc:/main/dir3$ # Woo I am in /main/dir3 root@mypc:/main/dir3$ pushd ../dir4 root@mypc:/main/dir4$ # Woo I am in /main/dir4 root@mypc:/main/dir4$ dirs # Now dir stack is: /main/dir4 /main/dir3 /main/dir2 /main/dir1 /main

I did the above since I would like to navigate back to those folders I documented! (using popd, instead of typing the relative or absolute path of each dir I want to go back into).

Note that if I manually cd, I will affect the top dir stack entry (which is always the current dir)

root@mypc:/main/dir4$ cd ..   # Now dir stack is:
# (note that /main appear in the leftmost as well which is the top of the stack)
/main /main/dir3 /main/dir2 /main/dir1 /main
root@mypc:/main$ 

Let's navigate backwards now:

root@mypc:/main$ popd
root@mypc:/main$     # Still in /main since it was at the top of the dir stack
root@mypc:/main$ dirs    # Stack is now:
/main/dir3 /main/dir2 /main/dir1 /main

root@mypc:/main$ popd root@mypc:/main/dir3$ popd # Woo in dir3 now, about to navigate to dir2 root@mypc:/main/dir2$ popd # Woo in dir2, about to navigate to dir1 root@mypc:/main/dir1$ dirs # Stack is now: /main

Again I can document whatever dir I want and then navigate manually to another dir then I will be able to easily return to the documented dir I inserted to the stack.

Use case 2: Navigating using numeric stack index

Lets say I pushed using pushd dir4 dir3 dir2 dir1, now running dir -v will show:

root@mypc:/main$ dirs -v
 0  /main/dir1  (this is the current dir you are in always)
 1  /main/dir2
 2  /main/dir3
 3  /main/dir4

Now you can do any Linux operation which involves directories using the stack index:

root@mypc:/main$ cp ~2/temp.txt ~3/new_temp.txt    # this will run in the background, something like:
# cp /main/dir2/temp.txt  /main/dir3/new_temp.txt

You can even delete a specific entry from the dir-stack:

root@mypc:/main$ popd ~4

Hope that using the words "documenting" or thinking about the dir-stack as some kind of Db simplifies the concept!

Mercury
  • 291
  • 1
    Actually, pushd doesn’t document the destination directory; it documents the directory you were in when you issued the command. Try cd dir1; pd dir2; pd dir3; pd dir4; cd dir5 and then run dirs. It’s confusing because the dirs command shows the current directory as the top element of the stack, but it’s ephemeral (volatile). – G-Man Says 'Reinstate Monica' Dec 27 '22 at 17:43
16

For bash, basically: instead of using cd one can use pushd to change directories. With practical usage: the history of visited directories is saved (correctly: stacked) and one can switch between them:

pushd /home; pushd /var; pushd /tmp

To see the stack use dirs and for easier navigation (to get the numbers of the "stack-entries" use:

dirs -v

Output:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp

Now utilize these numbers with cd and ~ like:

cd ~1

But these numbers are rearranged now and position "0" will change, so just pushd the directory to the top position twice (or use a dummy on position 0) like:

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp

Now 1..3 will keep their position

(To release the current directory from the stack/deleting it from history, use popd)

MacMartin
  • 2,924
14

pushd and popd allow you to manipulate the directories on stack.

When you pushd a directory, you put the current directory on the stack and change directory to the one specified as a parameter.

popd will allow you to go back to the directory on the stack.

If you repeat, the directory traversal will be sort of preserved and you can come back to the saved directories in reverse order from what you saved them in.

unxnut
  • 6,008
7

I found the usage of dirs/popd/pushd a bit uncomfortable. I came up with my personal solution in tcsh, by addind the following code into .alias

  foreach b (. , - 0 1 2 3 4 5 6 7 8 9 )
    alias p$b       'set a=`pwd`; echo $a >! ~/.mydir'$b
    alias cd$b      'cd "`cat ~/.mydir'$b'`"'
    alias del$b     'rm -v ~/.mydir'$b
    alias home$b    'set a="~"; echo $a >! ~/.mydir'$b
  end
    alias cdl       'grep / ~/.mydir*'

in this way I aliased, for instance, "p." to save the current working dir into file ~/.mydir. and "cd." to recover that dir whenever and wherever I like. "del." removes the corresponding file; "home." sets the dir to the home dir (equivalent to cd; p. ); "cdl" lists what are the saved dirs. Note that if you use ~/Dropbox/.mydir$b (or any other cloud service like e.g. ownCloud) instead of ~/.mydir$b you get a smart way to use your preferred dirs across different accounts and machines.

Vitelot
  • 71
6

Simply put, when you need to navigate between more than 2 directories, usually several times back & forth, as cd - just won't cut it with anything beyond 2 folders.

So, for example, instead of trying to re-come up with previous long paths by looking at your buffer's history or tab-completing a long pathway you simply stack the important ones up and if needed you conveniently move to them by their number alone. Rotating between complex directories structures and long paths becomes slick and swift.

The builtins also allow you to re-order the stack or pop out the directories you don't need anymore allowing flexibility in your workflow.

Directories stacking can also be used in scripts similarly for operations that span several directories.

DimiDak
  • 232
  • 2
  • 7
elig
  • 560
5

Using cd and cd - allows you to toggle between only your two most recently used directories. Your "directory working set" size is two.

Using pushd, you can keep an arbitrarily large number of directories in your working set.

I use pushd most of the time rather than cd. Once you've built up a stack of active directories with pushd directory_name, you can then jump between them all day with pushd ~#.

pushd dir1
pushd ../dir2
pushd /full/path/to/dir3

# There are now three directories in the stack.

pushd ~3
pushd ~2

# The same three directories are still on the stack, 
# just in a different order.

I use popd rarely, only when I want to remove a directory from the stack when I know I'm done using that directory.

Go to directory and remove it from the stack:

popd ~2

Stay in current directory and remove another directory from the stack:

popd +2

You end up with a working style that is similar to having multiple terminal windows or tabs open (one for each directory in which you're actively working), but all in one terminal. This saves screen real estate, plus, because the directory paths are all available in one shell, you can do things like:

  • copy files between directories you are currently working with
  • view or edit files in another directory without going there

Examples:

cp ~2/myfile.txt ~4
less ~2/myfile.txt

In tcsh (but not bash), you can even save your directory stack to a file and restore it later.

Save:

dirs -S ~/dirstack

Restore:

dirs -L ~/dirstack

Otherwise, just replace ~ in the bash examples with = for use in tcsh.

pushd =2
popd =4
popd +1
jskroch
  • 243
3

I am using it like this in my bash_profile and .bashrc like this

vi .bash_profile
alias dirs="dirs -v"
source d.sh
:wq

vi .bashrc
alias dirs="dirs -v"
:wq

vi d.sh
pushd ~/Documents/GIT/seiso-data
pushd ~/Documents/GIT/ewe/EosRegistry
pushd ~/Documents/GIT_LODGING/site-cookbooks
pushd ~/Documents/CHEF_LODGING
pushd  .
:wq

it helps me jump in between directories to most recent used on my terminal. :-) Hope it helps you to use pushd rather popd i use cd ~stackednumber

0

I found this nice explanation:

The pushd command takes your current directory and "pushes" it into a list for later, then it changes to another directory. It's like saying, "Save where I am, then go here."

The popd command takes the last directory you pushed and "pops" it off, taking you back there.

stevec
  • 181