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.).
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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
Method 2
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.
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ff8a8c9a8dbf899d">[email protected]</a>:~$ mkdir navigate
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a7d2d4c2d5e7d1c5">[email protected]</a>:~/navigate$ mkdir dir1
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2d585e485f6d5b4f">[email protected]</a>:~/navigate$ mkdir dir2
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2f5a5c4a5d6f594d">[email protected]</a>:~/navigate$ mkdir dir3
Then you can add all your folders to the stack:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1065637562506672">[email protected]</a>:~/navigate$ pushd dir1/
~/navigate/dir1 ~/navigate
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1164627463516773">[email protected]</a>:~/navigate/dir1$ pushd ../dir2/
~/navigate/dir2 ~/navigate/dir1 ~/navigate
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="92e7e1f7e0d2e4f0">[email protected]</a>:~/navigate/dir2$ pushd ../dir3/
~/navigate/dir3 ~/navigate/dir2 ~/navigate/dir1 ~/navigate
You can look it up by:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2653554354665044">[email protected]</a>:~/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dbaea8bea99badb9">[email protected]</a>:~/navigate/dir3$ pushd .
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4431372136043226">[email protected]</a>:~/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="295c5a4c5b695f4b">[email protected]</a>:~/navigate/dir3$ cd ~4
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fb8e889e89bb8d99">[email protected]</a>:~/navigate$ dirs -v
0 ~/navigate
1 ~/navigate/dir3
2 ~/navigate/dir2
3 ~/navigate/dir1
4 ~/navigate
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d5a0a6b0a795a3b7">[email protected]</a>:~/navigate$ cd ~3
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9ce9eff9eedceafe">[email protected]</a>:~/navigate/dir1$ dirs -v
0 ~/navigate/dir1
1 ~/navigate/dir3
2 ~/navigate/dir2
3 ~/navigate/dir1
4 ~/navigate
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0570766077457367">[email protected]</a>:~/navigate/dir1$ touch text.txt
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0174726473417763">[email protected]</a>:~/navigate/dir1$ cp text.txt ~2
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7603051304360014">[email protected]</a>:~/navigate/dir1$ ls ~2
text.txt
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4431372136043226">[email protected]</a>:~/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"
Method 3
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.
Method 4
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.
Method 5
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 log
To see the stack use dirs and for easier navigation (to get the numbers of the “stack-entries” use:
dirs -v
Output:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1b767e5b76627374686f">[email protected]</a>:/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="34595174594d5c5b4740">[email protected]</a>:/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)
Method 6
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
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c3b1acacb783aebab3a0">[email protected]</a>:/main/$ ls dir1 dir2 dir3 dir4 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4d3f2222390d20343d2e">[email protected]</a>:/main/$ dirs # prints the current stack /main <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="92e0fdfde6d2ffebe2f1">[email protected]</a>:/main/$ pushd dir1 # Will cd to dir1 and document dir1 in dir stack, stack is now: /main/dir1 /main <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dba9b4b4af9bb6a2abb8">[email protected]</a>:/main/dir1$ # I am now in /main/dir1 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d6a4b9b9a296bbafa6b5">[email protected]</a>:/main/dir1$ # Now let's go wild and document whatever I want <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="deacb1b1aa9eb3a7aebd">[email protected]</a>:/main/dir1$ pushd ../dir2 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="98eaf7f7ecd8f5e1e8fb">[email protected]</a>:/main/dir2$ # Woo I am in /main/dir2 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="62100d0d16220f1b1201">[email protected]</a>:/main/dir2$ pushd ../dir3 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="02706d6d76426f7b7261">[email protected]</a>:/main/dir3$ # Woo I am in /main/dir3 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7e0c11110a3e13070e1d">[email protected]</a>:/main/dir3$ pushd ../dir4 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1b6974746f5b76626b78">[email protected]</a>:/main/dir4$ # Woo I am in /main/dir4 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="01736e6e75416c787162">[email protected]</a>:/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)
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2654494952664b5f5645">[email protected]</a>:/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 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="483a27273c082531382b">[email protected]</a>:/main$
Let’s navigate backwards now:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="30425f5f44705d494053">[email protected]</a>:/main$ popd <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3644595942765b4f4655">[email protected]</a>:/main$ # Still in /main since it was at the top of the dir stack <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5a2835352e1a37232a39">[email protected]</a>:/main$ dirs # Stack is now: /main/dir3 /main/dir2 /main/dir1 /main <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c2b0adadb682afbbb2a1">[email protected]</a>:/main$ popd <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5c2e3333281c31252c3f">[email protected]</a>:/main/dir3$ popd # Woo in dir3 now, about to navigate to dir2 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="35475a5a4175584c4556">[email protected]</a>:/main/dir2$ popd # Woo in dir2, about to navigate to dir1 <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0775686873476a7e7764">[email protected]</a>:/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="85f7eaeaf1c5e8fcf5e6">[email protected]</a>:/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="30425f5f44705d494053">[email protected]</a>:/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:
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dcaeb3b3a89cb1a5acbf">[email protected]</a>:/main$ popd ~4
Hope that using the words “documenting” or thinking about the dir-stack as some kind of Db simplifies the concept!
Method 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.
Method 8
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.
Method 9
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
Method 10
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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0