I have the following .zshrc file in my home directory:

# modify the prompt to contain git branch name if applicable
git_prompt_info() {
  current_branch=$(git current-branch 2> /dev/null)
  if [[ -n $current_branch ]]; then
    echo " %{$fg_bold[green]%}$current_branch%{$reset_color%}"
setopt promptsubst
export PS1='${SSH_CONNECTION+"%{$fg_bold[green]%}%n@%m:"}%{$fg_bold[blue]%}%c%{$reset_color%}$(git_prompt_info) %# '

# load our own completion functions
fpath=(~/.zsh/completion $fpath)

# completion
autoload -U compinit

# load custom executable functions
for function in ~/.zsh/functions/*; do
  source $function

# makes color constants available
autoload -U colors

# enable colored output from ls, etc
export CLICOLOR=1

# history settings
setopt hist_ignore_all_dups inc_append_history

# awesome cd movements from zshkit
setopt autocd autopushd pushdminus pushdsilent pushdtohome cdablevars

# Enable extended globbing
setopt extendedglob

# Allow [ or ] whereever you want
unsetopt nomatch

# vi mode
bindkey -v
bindkey "^F" vi-cmd-mode
bindkey jj vi-cmd-mode

# handy keybindings
bindkey "^A" beginning-of-line
bindkey "^E" end-of-line
bindkey "^R" history-incremental-search-backward
bindkey "^P" history-search-backward
bindkey "^Y" accept-and-hold
bindkey "^N" insert-last-word
bindkey -s "^T" "^[Isudo ^[A" # "t" for "toughguy"

# aliases
[[ -f ~/.aliases ]] && source ~/.aliases

# extra files in ~/.zsh/configs/pre , ~/.zsh/configs , and ~/.zsh/configs/post
# these are loaded first, second, and third, respectively.
_load_settings() {
  if [ -d "$_dir" ]; then
    if [ -d "$_dir/pre" ]; then
      for config in "$_dir"/pre/**/*(N-.); do
        . $config

    for config in "$_dir"/**/*(N-.); do
      case "$config" in
          if [ -f $config ]; then
            . $config

    if [ -d "$_dir/post" ]; then
      for config in "$_dir"/post/**/*(N-.); do
        . $config
_load_settings "$HOME/.zsh/configs"

# Local config
[[ -f ~/.zshrc.local ]] && source ~/.zshrc.local

Unfortunately, when I start my terminal, I get the following error:

/home/steven/.zshrc:72: parse error near `fi'

The problem seems to be in my aliases files. I have two aliases files: 1. .aliases 2. .aliases.local

.aliases is loaded, and within that there is the following command to load .aliases.local:

[[ -f ~/.aliases.local ]] && source ~/.aliases.local

Within my .aliases.local file I have the two following aliases:

alias server='ssh -p xxx user@xx.xx.xxx.xxx'
alias do='ssh -L xxxx: -N -f -l user -p xxxx xx.xx.xxx.xxx'

These are basically aliases to ssh into my server (the first alias), and also to establish a secure tunnel so I can use a VNC client to the server.

These two aliases are working correctly, but when I define them in .aliases.local, I keep getting this error. What am I doing wrong?

  • Nothing obvious here. Do you get the same error if there aren't any included files? In particular .aliases could be setting up a bad alias. – Gilles Apr 11 '15 at 22:18
  • You are right - it must be my aliases file. When I move my .aliases file so that it doesn't load, I don't get the error. – Steven L. Apr 12 '15 at 0:54
  • I've updated the original question to reflect this information @Gilles – Steven L. Apr 12 '15 at 1:01

do is a reserved word in the shell. It's part of the syntax of while and for loops. When you define it as an alias, the alias takes precedence over the reserved word. So the shell sees, after alias expansion:

if [ -d "$_dir/pre" ]; then
  for config in "$_dir"/pre/**/*(N-.); ssh -L xxxx: -N -f -l user -p xxxx xx.xx.xxx.xxx
    . $config

I don't know why zsh is complaining about the fi and not about the done or the lack of do after the semicolon, but anyhow, this isn't valid syntax.

You need to pick a different name for your alias. Avoid all reserved words.

  • @Gilles; Note that do is no reserved word in bourne like shells; it's perfectly valid to write, e.g., for do in do doo dooo ; do print echo $do ; done. You just can't have it at places where a command is expected. – Janis Apr 12 '15 at 7:43
  • @Janis “Reserved word” is what most shell manuals, including ksh and POSIX and (most relevantly for this answer) zsh use. The Bourne manual doesn't give a name. They are indeed only reserved at the beginning of a command (and a few other contexts), but they are called “reserved words” nonetheless. – Gilles Apr 12 '15 at 11:27
  • @Gilles; the ksh documentation, e.g., felt the need to explicitly clarify that they are "reserved" only in "specific contexts", because the term "reserved word" is generally not defined that way but it has an absolute meaning about whether it may or may not be used by users. I think in the broad context of Stack Exchange questions that should be made clear. I propose to not use the term "Reserved Word" unconditionally, but only if it's truely reserved (as usually programming languages use the term), or to explicitly note the restriction (as the ksh docs do). – Janis Apr 12 '15 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.