Is there a difference between the behavior of pushd/popd in bash vs zsh? It seems in zsh cd, cd- behaves exactly the same as pushd/popd (which adds/pops directory automatically when cd) while in bash cd doesn't affect the dir stack.

If someone can give me a pointer that would be great.

  • 1
    I can only speak to bash: using cd sets the shell variable OLDPWD to the previous directory, and cd - gets translated to cd "$OLDPWD". Mar 29, 2016 at 20:26
  • @glennjackman, thanks. Does that mean in bash cd has nothing to do w/ pushd/popd? Mar 29, 2016 at 20:27
  • 1
    I just checked, and pushd also sets OLDPWD Mar 29, 2016 at 20:28
  • And the dirstack, returned by dirs always holds the PWD as the first element Mar 29, 2016 at 20:29
  • yes, but it also makes a lot sense if cd doesn't touch dir stacks which is managed by pushd/popd in bash. Mar 29, 2016 at 20:30

1 Answer 1


It depends. In zsh you can configure cd to push the old directory on the directory stack automatically, but it is not the default setting.

As far as I can tell zsh with default settings behaves very similar to bash:

  • cd somedir
    • change directory to somedir
    • save the original directory in OLDPWD
    • set PWD="somedir"
    • replace top element of the directory stack (as shown by dirs) with somedir (the number of elements on the stack does not change).
  • cd -:
    • change directory to $OLDPWD
    • swap values of PWD and OLDPWD
    • modify the top element of the directory stack to reflect (the new) PWD
  • pushd somedir:
    • change directory to somedir
    • save original directory in OLDPWD
    • set PWD="somedir"
    • push somedir onto the directory stack (extending it by one element)
  • popd:
    • save original directory in OLDPWD
    • remove first element of the directory stack
    • change directory to the new top element of the directory stack
    • set PWD to the new top element of the directory stack

Note: Whether the present working directory is considered an element of the directory stack differs between zsh and bash. I used bash as reference for the above lists.

  • In bash the present working directory is considered to be the top element of the directory stack. The man 1 bash says:

    pushd [-n] [dir]

    […] Adds dir to the directory stack at the top, making it the new current working directory as if it had been supplied as the argument to the cd builtin. […]

    Printing DIRSTACK (echo ${dirstack[@]}) confirms that the first element is identical to $PWD.

  • In zsh the present working directory is not part of the directory stack (but still shown with dirs). man 1 zshbuiltins says:

    pushd [ -qsLP ] [ arg ]

    […] Change the current directory, and push the old current directory onto the directory stack. In the first form, change the current directory to arg. […]

    Printing dirstack (echo ${dirstack[@]}) and comparing it to the output of dirs should show that the PWD is not part of `dirstack.

In both shells dirs prints the present working directory as the first element. Also in both shells, the directory stack element with the index 1 refers to the directory which was current before the last pushd. That is because arrays in zsh are usually numbered from 1, while they are numbered from 0 in bash. So there is little practical difference

As said above, this behavior can be modified in zsh.

If you set the AUTO_PUSHD option in zsh (setopt autopushd) cd somedir behaves like pushd somedir, the previous directory is pushed onto the directory stack automatically. This is probably the case on your machine. You can run setopt to get a list of options that are not set the default way. See, whether autopushd appears in the list.

But this does not modify cd - to behave like popd. Instead it just pushes $PWD onto the directory stack, and changes directory to $OLDPWD. That means repeatedly calling cd - will actually grow the directory stack (($PWD $OLDPWD $PWD $OLDPWD $PWD …)). If it actually does behave exactly like popd on your system, I would suggest if cd is actually the builtin (whence -v cd); it is possible that its replaced with an alias or function.

As the directory stack will grow rather quickly with AUTO_PUSHD enabled, you can limit its size by setting the parameter DIRSTACKSIZE to the desired maximum size.
You can also prevent duplicates by setting the PUSHD_IGNORE_DUPS option.
For more options have a look at the manual.

  • what is the purpose of the directory stack other than looking at it via dirs?
    – xeruf
    May 8, 2018 at 21:56
  • 1
    @Xerus It allows to go back to previously visited directories with popd without the need to type (or even know) the path.
    – Adaephon
    May 8, 2018 at 23:05
  • Can example be added here? May 26, 2020 at 10:19
  • 2
    Can use e.g. pushd directory; pushd subdirectory. At the end you'll be in ./directory/subdirectory. A popd takes you back to ./directory and another popd takes you to . However cd directory; cd subdirectory; cd -; cd - leaves you in ./directory no matter how many cd - commands you use because there is only ONE "OLDPWD" saved. Sep 1, 2020 at 15:59
  • 2
    For those using prezto, the 'directory' module sets AUTO_PUSHD, sneakily. You can comment that out here: ~/.zprezto/modules/directory/init.zsh
    – ijoseph
    Sep 4, 2021 at 2:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .