Take the 2-minute tour ×

With zsh (and oh-my-zsh), is it possible to always run a command after a certain other command? I want to always run an ls after cding to a directory, rather than running cd example; ls every time.

I have tried:

function cd {
  cd $1

But it seems to exit zsh when run, without any output (stack overflow?). Changing the name of the function makes it work as intended, however I would rather still use the cd command.

alias cd='cd $1;ls'

Lists the specified directory, but doesn't actually change the working directory.


share|improve this question
The && command might be useful. (e.g. alias cd='cd $1;ls && ls). –  Hennes May 30 '13 at 0:34
I don't think aliases are suitable for this kind of thing, use a function instead. –  evilsoup May 30 '13 at 0:36
@Hennes that appears to ls the current directory and the new one, but still doesn't move the actual shell. –  JJ56 May 30 '13 at 0:39
Ah. Not logged into a zsh atm, but && ls $1 ? –  Hennes May 30 '13 at 0:40
@evilsoup I agree, the function in my post when renamed works. How can I make it work while still called cd? –  JJ56 May 30 '13 at 0:40

2 Answers 2

Although you already solved you problem yourself, I want to elaborate a little bit.

Why your alias does not work:

@evilsoup already hinted at it, but to state it clearly: Aliases (in zsh and bash) are not able to take arguments (whereas in csh they can). Think of it as a simple string replacement. Hence with alias cd='cd $1;ls' defined, the command cd foo expands to cd ; ls foo because $1 is empty (not defines in this context) and you see the content of foo/ but the shell does cd into into the current directory (no argument after cd).

Why your function as in the question does not work:

You define a function cd, which itself calls cd. So you end up in an infinite loop. The current zsh version (5.0.2) doesn't segfault, but gives an error:

cd:1: maximum nested function level reached

The solution is to use builtin cd inside your function cd -- as you already worked out yourself.

Why your function (from there) can be improved

You are redefining the cd function. That works fine, if you call it explicitly. But zsh offers the AUTO_CD option (to be set with setopt AUTO_CD):

If a command is issued that can't be executed as a normal command, and the command is the name of a directory, perform the cd command to that directory.

That means you can change to /var by simply typing /var instead of cd /var. In this case your cd function isn't called and you didn't see the content of /var automatically.

pushd and popd are other cases where a redefined cd command doesn't help.

The ZSH way

Stephane Chazelas on SE/UL already gave the zsh-ish way, as pointed out by @evilsoup in the comments: Do not redefine cd, but use the hook function chpwd(), which is there for exactly that reason:

chpwd Executed whenever the current working directory is changed.

So just add

function chpwd() {

to your ~/.zshrc. (A short form of that is chpwd() ls as given in the linked answer.)

share|improve this answer

This post on Unix/Linux solved it for me:

function cd {
  builtin cd "$@" && ls -F

It's about bash, but works for me in zsh.

share|improve this answer

Your Answer


