Shell builtins · bash builtin
popd
Remove the top directory from the directory stack and change back to the next one.
popd [-n] [+N | -N]
popd is the other half of pushd. It removes the top entry of the directory stack and
changes to the entry that is now on top, which is the directory you were in before the last
pushd. Like pushd, it prints the resulting stack.
With +N or -N it removes a specific entry instead (counted from the top or the bottom, as
dirs -v numbers them) without leaving the current directory, unless N points at the top.
-n removes the second entry and stays put. To empty the whole stack except the current
directory, use dirs -c.
popd fails with "directory stack empty" when there is nothing to return to, which happens
when it is called without a matching pushd, for example after an early return skipped
one.
Examples
Return to the previous directory
pushd data >/dev/null
pushd ../logs >/dev/null
dirs -v
popd
popd
0 ~/demo/logs 1 ~/demo/data 2 ~/demo ~/demo/data ~/demo ~/demo
Each popd discards the top entry, changes to the next one and prints the stack. After
two pops you are back in ~/demo with a single entry left.
Use popd quietly in a script
pushd /tmp >/dev/null
touch scratch.$$
popd >/dev/null
echo "back in $PWD"
back in /home/dev/demo
Redirecting stdout to /dev/null hides the stack printout; errors still reach stderr.
popd with an empty stack fails
popd
echo "status $?, still in $PWD"
/bin/bash: line 1: popd: directory stack empty status 1, still in /home/dev/demo
There is only the current directory on the stack, so there is nothing to pop. popd
reports the empty stack and returns 1.
Remove a specific entry with +N
pushd /tmp >/dev/null; pushd /etc >/dev/null; pushd /usr >/dev/null
dirs -v
popd +2 >/dev/null
echo "after popd +2, still in $PWD:"
dirs -v
0 /usr 1 /etc 2 /tmp 3 ~/demo after popd +2, still in /usr: 0 /usr 1 /etc 2 ~/demo
popd +2 deletes entry 2 (/tmp) and leaves the current directory alone. The entries
below it move up one place.
Drop the next entry but stay here with -n
pushd /etc >/dev/null; pushd /usr >/dev/null
popd -n >/dev/null
echo "in $PWD"
dirs -v
in /usr 0 /usr 1 ~/demo
-n removes the second entry (/etc) instead of the top, so the current directory does
not change.
Clear the stack with dirs -c
pushd /tmp >/dev/null; pushd /etc >/dev/null
dirs -c
dirs -v
popd
0 /etc /bin/bash: line 4: popd: directory stack empty
dirs -c empties the stack apart from the current directory, so the next popd has
nothing to return to and fails.
Keep pushd and popd balanced in functions
count_c_files() {
pushd src >/dev/null || return
local n
n=$(ls *.c | wc -l)
popd >/dev/null
echo "$n C file(s)"
}
count_c_files
echo "caller still in $PWD"
1 C file(s) caller still in /home/dev/demo
Every path out of the function must pass a popd; an early return between the two
would leave the caller in src. Here the || return comes before anything was pushed,
so it is safe.
popd does not exist in sh
popd
/bin/sh: 1: popd: not found
dash, the /bin/sh on Debian and Ubuntu, has no directory stack. In POSIX scripts save
the directory yourself (old=$PWD; cd dir; ...; cd "$old") or use a subshell.
Common pitfalls
An early
returnorexitpath betweenpushdandpopdleaves the stack, and the current directory, out of balance.popd +Ncounts from 0 at the top, likedirs -v;popd -Ncounts from the bottom. Checkdirs -vfirst.Calling
popdafter a plaincd:cdreplaced the top entry rather than pushing, sopopdgoes back further than expected.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
popdis a bash and zsh builtin, not POSIX; dash and other plainshimplementations lack it.
Options worth knowing
A selection, described in our own words. For the full list, see bash(1), SHELL BUILTIN COMMANDS.
| Option | What it does |
|---|---|
-n | Remove the second entry instead of the top, without changing directory. |
Related
pushdChange to a directory and remember the previous one on a stack, so popd can return to it.cdChange the shell's current working directory.pwdPrint the full path of the current working directory.- Subshells and command groupingThe difference between ( ... ) and { ...; }, what a subshell inherits and what it cannot change, which constructs create one, and what that costs.
- FunctionsDefining and calling bash functions, arguments, local variables, return status versus output, namerefs, and sourcing a function library.