How to Use PUSHD and POPD in Shell Scripting




by Howard Fosdick  © 2025 RexxInfo.org



Moving between directories while interacting with the shell can be tiresome if you traverse lots of directories. You may even get confused as to where you are in the tree structure.

The pushd and popd shell commands offer a simple way to navigate any directory structure quickly and easily. They're a powerful alternative to issuing a cascade of cd and pwd commands.

pushd and popd are especially useful in scripting. With them, your scripts can easily change back and forth between directories however processing dictates.

This article shows how to easily navigate directory trees using the shell's pushd and popd commands.

Towards the end of the article, we'll present a scripting example that traverses an entire directory structure. It converts all PNG files in the directory structure to WEBP files, which saves a lot of storage space. pushd and popd make this script easy to write.

Which Shells Support Pushd and Popd?


Most-- but not all -- mainstream shells support the pushd and popd shell commands. Here's a list:


 Shell:
Pushd and Popd:
  
 Bash
 Yes
 Zsh
 Yes
 Tcsh
 Yes
 Csh
 Yes
 Fish
 Yes
 Sh
 No
 Dash
 No
 Ksh (ksh93u+)
 No


The examples in this article were all tested with the Bash shell.

To see which shell you're using, issue this command:
echo $0
It's easy to install nearly any Linux shell through any of the mainstream Linux code repositories. To list what shells you currently have installed, enter this command:
cat /etc/shells
If you have more than one shell installed, tell Linux which shell to use in your shell scripts by coding this command as the first line of code:
#!/bin/bash
This so-called "shebang" command contains the full directory path of the shell executable you want Linux to run in processing your script.

The Directory Stack



The Directory Stack The pushd and popd commands manipulate a storage structure inside the shell called the directory stack. The directory stack contains a list of directories. It's designed to help you keep track of your navigation across directories.

You add or push an item onto the directory stack, and retrieve or pop it back out.

The last item pushed into the stack is always the first one popped back out. Thus the stack is a "last-in, first-out" storage area (often abbreviated as LIFO).

At any time, you can issue the dirs command to display the directory stack's contents.



Examples



Let's open a terminal, then issue a dirs command to see the directory stack's contents.

By default, the first stack entry is the always the current directory. In this case, that's Bob's home directory, as represented by the tilde ( ~ ):
bob@Compaq:~$ dirs
~

If you wish to see the full directory name, issue dirs with the -l option:
bob@Compaq:~$ dirs -l
/home/bob
Now, use the pushd command to change the current directory to any new directory you specify. In this case, we'll change to the football subdirectory:
bob@Compaq:~$ pushd football
~/football ~
bob@Compaq:~/football$

The pushd command changes to the directory you specify, just as if you had entered the command:  cd football. The command also adds the new directory to the stack. Then it echoes stack's contents to the terminal, with the newest entry listed to the left side. That is your current working directory.

So, the stack now contains two directory entries: ~/football and ~ . We can verify this by a dirs command:
bob@Compaq:~/football$ dirs
~/football ~
bob@Compaq:~/football$
The default Bash command prompt also shows that we've changed the current directory to the new directory specified on the pushd command, since it now looks like this:   bob@Compaq:~/football$.

Now, issue a popd command. This removes the topmost entry from the stack, changes the current directory to the new topmost entry, and echoes the stack's contents to the terminal:
bob@Compaq:~/football$ popd
~
bob@Compaq:~$

So, popd reversed the effects of the previous pushd command. It removed the ~/football entry from the stack, and then changed the current directory to the new topmost stack entry. In this case, that is Bob's home directory, represented by the tilde ( ~ ).


More Examples



Let's put these commands to work by navigating a directory containing different kinds of football rules. Here's the directory tree:


The Football Directory Tree


These example commands maneuver through the directory tree. At any point, the default Bash prompt displays where we are in the directory structure, since it embeds the current directory in its prompt.

The pushd and popd commands themselves always echo the directory stack contents after they complete their operations:

bob@Compaq:~$ cd football                                 # Initialize by getting into the FOOTBALL directory
bob@Compaq:~/football$ dirs                               # List our initial directory stack
~/football

bob@Compaq:~/football$ pushd british_isles_rules          # Push BRITISH_ISLES_RULES onto the stack
~/football/british_isles_rules ~/football

bob@Compaq:~/football/british_isles_rules$ pushd rugby    # Push RUGBY onto the stack
~/football/british_isles_rules/rugby ~/football/british_isles_rules ~/football

bob@Compaq:~/football/british_isles_rules/rugby$ dirs -v  # Display the stack with position numbers
0  ~/football/british_isles_rules/rugby
1  ~/football/british_isles_rules
2  ~/football/

bob@Compaq:~/football/british_lsles_rules/rugby$ popd     # Pop RUGBY off the stack
~/football/british_isles_rules ~/football

bob@Compaq:~/football/british_isles_rules$ pushd gaelic   # Push GAELIC onto the stack
~/football/british_isles_rules/gaelic ~/football/british_isles_rules ~/football

bob@Compaq:~/football/british_isles_rules/gaelic$ popd    # Pop GAELIC off the stack
~/football/british_isles_rules ~/football

bob@Compaq:~/football/british_isles_rules$ popd           # Pop BRITISH_ISLES_RULES off the stack
~/football

bob@Compaq:~/football$ dirs                               # We're back at our starting point
~/football

Note how pushd and popd always list the topmost directory in the stack to the left, with the bottom-most to the right. The dirs -v command displays the stack's contents vertically, along with the numeric position for each stack entry. I find the vertical listing a bit easier to read, so I routinely use this format.


To Summarize



To sum it all up, pushd performs three actions:
  1. Changes to the directory you specify (just as if you had entered a cd command)
  2. Adds that directory to the stack
  3. Echoes the stack's current contents to standard output


popd performs the three inverse actions:

  1. Removes the most recent directory entry from the stack
  2. Changes the directory back to the new topmost stack entry
  3. Echoes the stack's current contents to standard output

It's possible to rotate the order of the elements in the stack by specifying an option on the pushd command. Similarly, you can retrieve a specific entry from the stack by coding popd with a numeric position. These options can be useful when scripting.


Scripting



The directory stack is especially useful in script writing.

For example, say you want to process a command in a user's home directory and each of its subdirectories. Or perhaps you need your script to issue some commands in every directory on the computer.

In either case, your script needs to be able to traverse any arbitrary tree structure. A directory stack makes this problem trivial.

To start coding the script, we need a way to list all the subdirectories to a specified directory. The find command helps in this.

Start the find command's search for directories in the current directory, as represented by a period ( . ). Code the -type d option so that find returns a list of directories only (no file names).

So, this command returns a list of the current directory and all its subdirectories:

find . -type d 

Next, capture this list of directories by piping it directly into a read command. This example code captures the entire directory tree structure, starting at the current directory, and echoes it to the terminal.

The code inside the do... done loop executes for each directory retrieved by the find command:

find . -type d | while read dir
do
   echo "$dir"        # Display directory name to the terminal (quote marks handle names containing spaces)
done

So, for our football directory example, this script produces output like this:

.
./australian_rules
./canadian_rules
./british_isles_rules
./british_isles_rules/rugby
./british_isles_rules/rugby/rugby_league
./british_isles_rules/rugby/rugby_union
./british_isles_rules/gaelic
./american_rules

If we're going to run a set of commands against each directory, we need an easy way to keep track of where we are in the directory structure at any point in time. You could code cd and pwd commands to manually manage this.

The directory stack and its pushd and popd commands offer another way.

Here's a practical scripting example. The script below converts every PNG image file in the football directory tree to WEBP format. WEBP files reclaim up to 90% of the space used by PNG images. (WEBP is a lossy format, meaning it achieves this dramatic storage space savings by reducing the sharpness (or resolution) of the image.)

Our script uses the Imagemagick convert command to perform the PNG to WEBP image conversion, so you must have the Imagemagick package installed in order to run this script. You can install it from any Linux repository if it's not already on your computer.

Here's the script:


#!/bin/bash
find . -type d | while read dir
do
   pushd "$dir" >/dev/null          # Change to the next directory to run the commands

   #
   # Convert all PNG files in the given directory to WEBP files
   #
   for file in *.png ; do               
      convert "$file" "$file".webp  2>/dev/null
      # delete source PNG file here if desired
   done

   popd          >/dev/null         # Change back to the prior directory
done 

This script uses the pushd command to save the current directory, and then change to the subdirectory provided by the read command. Then, the script runs the convert command for each PNG file in that directory. Finally, the popd command takes the script back to its prior directory in the tree.

The script suppresses the outputs of the pushd and popd commands by sending them to >/dev/null. The directory and file names the script processes -- the variables "$dir" and "$file" -- are enclosed inside double quotation marks to ensure that the script handles names that include embedded spaces.

So using the directory stack helps you easily traverse any arbitrary directory structure. Then you can issue commands against the files in each subdirectory.

Here, we applied this concept to convert from PNG to WEBP image formats and reclaim disk storage space. But you could replace the convert command with any other command sequence you want. The directory stack with pushd and popd gives your scripts tremendous power.


Summary



The directory stack and its pushd, popd, and dirs commands offer a simple way to navigate any directory tree. They're quick and convenient when you interactively navigate the directory structure.

They're especially useful in writing scripts. They can trivialize a problem like processing an entire directory tree, as was demonstrated in the last example script.

-------------------------------

Related Articles


Linux Commands to Display Hardware Information
How to Identify Linux Performance Bottlenecks
How to Upgrade Linux PC Hardware
How to Shrink PDF Files
How to Traverse Directories in Scripts
How to Use PUSHD and POPD
Reclaim Big Disk Space by File Conversions
Linux Performance Tips
Bash to Python Mapping & Comparison

Back to RexxInfo.org