Always run a command after another command

Solution 1:

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() {
  ls
}

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

Solution 2:

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.