How do I use pushd and popd commands?
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.).
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.
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
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.
There is a really useful use case for pushd
and popd
commands 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"
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
)
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.
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
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.
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
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!
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.