Explanations for each zsh template file

From OS X Scientific Computing

Jump to: navigation, search
Return to ZSH on OS X.


The /etc files

These are the "master" control files for zsh. They control everything else in the next two sections. As of revision 2.0.0, almost everything is done from /etc/zshrc. The reason for this is that simply issuing

/bin/zsh -f

as is done, for example, in shell scripts, will prevent all of the non-standard customizations from being invoked.


The instruction to source the /etc/zshenv file, when present, is hard-coded in the /bin/zsh binary. This file is always run, even if zsh -f is used, so it is best for us not to put any stuff in this file that one might only want in an interactive shell session. (Non-interactive sessions include things like shell scripts, which often start with the line #!/bin/zsh -f. If you want crucial environment variables and modifications to $PATH and so on available to shell scripts, it is a good idea to put such things in the zshenv file.

Our /etc/zshenv is basically a minimal skeleton.

First, we define a minimal $PATH

/usr/libexec/path_helper -s

(on OS X) to obtain the minimal path. (This is already done by default on OS X in /etc/profile and /etc/zprofile, so even that is probably not necessary. But doing so ensures we start off with the desired minimal elements of the $path array.)

Second, assign $ZDOT

Then we assign the environment variable $ZDOT to /Library/init/zsh in OS X or /etc/zsh/init/zsh in Linux. You can change this if you want to put the customization files elsewhere.

Third, source everything in $ZDOT/zshenv.d

Finally, /etc/zshenv will check for the presence of subsidiary environment files placed within $ZDOT/zshenv.d and will source any that are found (unless disabled) in alphaneumeric order. You can put any file containing zsh syntax in this directory and it will be sourced automatically. But unless you need to set further environment variables or make other modifications that are required even within non-interactive sessions, it is best not to put anything in this directory. Instead, use $ZDOT/zshrc.d or better still, $ZDOT/zshrc_local.d . This simplified file structure permits greater organization, modularity, and control, and it should make things a bit less confusing compared to version 1.X.


First, source everything in $ZDOT/zshrc.d

In analogy with /etc/zshenv, /etc/zshrc will check for the presence of subsidiary environment files placed within $ZDOT/zshrc.d and will source all the files that are found (unless disabled) in alphaneumeric order. You can put any file containing zsh syntax in this directory, or modify any that is already in this directory, and it will be sourced automatically (unless the file name contains the word disabled.

Almost everything distributed with the zsh-templates set of files winds up in $ZDOT/zshrc.d. You can disable any file foo simply by renaming it to foo.disabled. You can also modify any file. However, when possible, instead of modifying the file, copy it to $ZDOT/zshrc_local.d, and then modify the file, keeping only the relevant change. This will minimize the changes of your changes getting clobbered when you update to a newer version.

Second, source any file the user placed into $ZDOT/zshrc_local.d

If possible, it is best to put modifications that are desired, and that are to be made available system-wide, into $ZDOT/zshrc_local.d . In other words, if you don't like an existing alias or variable assignment, it is easiest simply to reassign the variable by putting a directive in this directory. Similarly, for functions, you can put new functions, or re-defined functions, in $ZDOT/zshrc_local.d/site-functions . These will over-ride previously assigned functional declarations. This site-function directory is put at the head of $FPATH, so it will be seen by the shell first.

This simplified approach will permit greater organization, modularity, and finer user-control, and will be more robust in terms of surviving upgrades.


Files placed in $ZDOT/zshenv.d are sourced from /etc/zshenv. For that reason, anything placed in $ZDOT/zshenv.d will always be read, even in non-interactive sessions.

In practice, this means that you probably won't want to put anything into this directory. Possible exceptions to this might include initializing Fink or Macports environments (and in anticipation of this, two disabled files are provided as templates that you can activate by renaming them -- if you must). Again, it is best to avoid putting anything else in this directory. Read the README.txt file for more information.

If you have to add to the $PATH variable for everyone on the system, you can do so in a shell-independent way on OS X >= 10.5 in /etc/paths.d


Almost everything now happens in here. The reason is that you can skip over this simply by issuing the -f flag upon invoking the shell, i.e.,

/bin/zsh -f

which is standard practice in, for example, shell scripts.

The best way to make changes

Although you can add to and edit the contents of this directory, you are almost always much better off adding directives (aliases, environment variables, options, functions and so forth) to the $ZDOT/zshrc_local.d directory instead. This directory is reserved for site-modifications, and any changes you make should survive updates with minimal fuss. Hence using $ZDOT/zshrc_local.d to make systemwide modifications is more robust


If you have Fink installed in /sw, fink will be initialized by sourcing the file /sw/bin/init.sh. This will put /sw/bin and /sw/sbin at the head of $PATH, which is the default fink behavior.

If you have fink installed somewhere other than /sw, you need to edit this file accordingly.

If you have fink AND Macports installed, 002_macports_env.zsh will be sourced next, which will put /opt/local/bin ahead of /sw/bin, so be aware of this. To reverse this behavior, change the prefix number of this file to 003.


If you have Macports installed in /opt/local, this will put /opt/local/bin and /opt/local/sbin at the head of $PATH.

If you have Macports installed somewhere other than /opt/local, you need to edit this file accordingly.

If you have fink AND Macports installed, 001_macports_env.zsh will be sourced after the fink file, which will put /opt/local/bin ahead of /sw/bin, so be aware of this. To reverse this behavior, change the prefix number of this file to 000.


This file builds $PATH, $MANPATH and associated variables by testing for the presence of various bin directories and adding them. Duplicates are eliminated with the zsh shell command

typeset -U path

which has won the Good Housekeeping seal of approval.

Note that the $FPATH is not set here, but instead in file 031 below.

Assembling the $PATH variable

Assembling $PATH (and the corresponding $path array) is the single most important task this file performs. If you are having a PATH problem, look here first.

The main trick to setting $PATH is to make certain you haven't left anything out. We go through and systematically test for the presence of every executable directory, and either prepend or append it to the $PATH variable. You should, as a bare minimum, have these in your OS X $PATH:


So we keep adding on to that. If every executable directory this process tests for exists, you will have the following in your $PATH:

  • /bin
  • /sbin
  • /usr/bin
  • /usr/sbin
  • /usr/libexec
  • /usr/X11R6/bin and/or /usr/X11/bin
  • /Developer/Tools
  • /Library/Tcl/bin
  • /usr/local/bin
  • /usr/local/sbin
  • ~/bin
  • ~/.bin

By default, we don't add " . " (the current directory) by at the end, but the user can do so in ~/.zshrc, where it is fairly safe to have it.

The $MANPATH variable

The $MANPATH is assembled using a procedure similar to what was done for $PATH.

The $HELPDIR variable and run-help command

The $HELPDIR is assembled using a procedure similar to that for $PATH and $FPATH and $MANPATH. Note that is is a better implementation that what zsh uses by default, but it is done in such a way as to remain compatible with either the supplied run-help function or my augmented run-help function. man run-help

$HELPDIR and $helpdir are then explicitly tied together like $PATH and $path


Some very standard, non-invasive and useful aliases are defined in this file. These were originally authored and/or assembled by Gary Kerbaugh.


More aliases are defined here. These are more idiosyncratic aliases, some of which you may simply hate and want to comment out. Most are harmless.

rm -i

The one alias most likely to cause objections is

alias rm="rm -i"

I do this for safety reasons (it prompts you to ask if you really want to remove the file), but there are lots of arguments for why you might not want to do this.


This one I really like, and was able to construct it with the help of Gary Kerbaugh. It is an example of an alias in which it is hard to imagine how to write a function to do the same thing (usually you are better off having functions than aliases):

alias fu='sudo $( fc -ln -1)'

So you type a command, and the reply is that you don't have root permissions. Then you just type the inspirational response


and your command is repeated, with the magical "sudo" prepended.


Sometimes the powerful and generally helpful zsh automatic correction behavior can be irritating. You can over-ride it with the "nocorrect" command:

alias mkdir='nocorrect mkdir'
alias mv='nocorrect mv'
alias cp='nocorrect cp'
alias touch='nocorrect touch'
alias ln='nocorrect ln'

share directory stack between shell sessions


There are a number of other aliases in this file that you might like to use, so it is worth reading the file. The last on the list is the


command. It is a complicated alias to my gdirs command. Typing the command gives a listing of the last 20 unique directories visited, and unlike the standard dirs command, this is shared among terminal sessions:

% cd? 
1 /usr/share/zsh/4.3.2/functions
2 /Users/wgscott
3 /Users/wgscott/Desktop
20 /Users/wgscott/death_warrants
gdirs: the gui version

gdirs gives a selectable gui menu version of this listing.


Functions distributed with zsh can be loaded here. Most are off by default.

The easiest and most robust way to change these settings is to copy this file to $ZDOT/zshrc_local.d and then edit it, uncommenting the autoload command for each function you want to make available.

In the distributed file, only two functions are loaded. These are very useful. zcalc is like bc, but better, and zmv is an enhanced mv utility. Combined with the noglob option, it can be used as a "batch rename" utility, which we'll call mmv.

   autoload -U zcalc
   autoload -U zmv 
   # set these associated aliases:
   alias mmv='noglob zmv -W'   # user-friendly version of zmv

that permits you to batch-rename a set of files with one command, eg:

foo_001.img ... foo_720.img can all be renamed to start with bar_ like this:

mmv foo_*.img bar_*.img

and zsh does the right thing.

The $FPATH for these functions is built into the zsh binary during compilation, so there is no need to define it explicitly.


The $FPATH variable is assembled here.

A minimal $FPATH is hard-coded into the zsh binary that enables the shell to find the functions distributed with zsh. However, you can add elements to $FPATH in exactly the same way that one does for $PATH.

zsh will look for individual zsh shell script files contained in directories defined in the $FPATH variable and will make them available for loading on demand. (You have to issue commands like "autoload -U zcalc", which is what the rest of this file does).

By default, directories such as /usr/share/zsh/X.Y.Z/functions and /usr/share/zsh/site-functions are hard-wired into the zsh $FPATH, so we take care not to clobber them. We test for additional function directories, so you could potentially have the following in $PATH if all are present:

The command

typeset -U fpath

keeps $FPATH and the cojoined $fpath array from accumulating duplicates.


Functions that the zsh-templates people wrote or co-opted, can be loaded here. Most are harmless, but if you want to get rid of them or load ones that aren't loaded by default, you will probably want to make some changes.

In the future, I will probably split this into at least three separate files.

The easiest and most robust way to change these settings is to copy this file to $ZDOT/zshrc_local.d and then edit it, uncommenting the autoload command for each function you want to make available.

This file does the same thing as the functions file, but for the functions distributed with zsh-templates. I have tried to comment the file to some degree, but the best way to find out what the functions do is to consult the (almost complete) on-line documentation or man pages.

User Control Options

I've tried to group these according to whether or not you might be likely to use them. For further control, at the top of the page, I define three environment variables:


Change 'NO' to 'YES' if you want the second or third batch read by default. Alternatively, if you put a file (even an empty one) called ~/.zlocalfxn in a user's home directory, the 'NO' setting will be over-ridden for that user, so issuing the command

touch ~/.zlocalfxn

is the equivalent to setting the second variable to 'YES' for a single user. Similarly, for the third option, if you have installed crystallographic software via fink, and therefore have


the crystallography functions that an ordinary user would not want will become available. (These functions reside in a specific subdirectory described in the next section.)

The function files that this file makes available reside in the subdirectory called local-functions.


Most of the Key Bindings are pretty standard, and are distributed with the zshenv sample file. However, there is a check to see if the individual user will want to use vi rather than the default emacs key bindings:

 if [[ -f ~/.zshvi ]];then
       bindkey -v
       print "Using vi key bindings!"
       bindkey -e

So if you want to use vi key bindings, simply issue the command

touch ~/.zshvi

and if you want to go back to the default emacs key bindings, issue

rm ~/.zshvi


The corresponding file for vi keybindings is disabled by default. It is probably not a good idea to set the shell to use vi keybindings system-wide by default, unless you really enjoy annoying people or you run a serious vi cult.


Other keybindings are set here.

A few are worth mentioning:

bindkey '\e[A'  history-search-backward 
bindkey '\e[B'  history-search-forward

These are bound to the up and down arrows, so that when you type the beginning of a command, and then hit the up arrow, you can search through the command history, filtering with whatever prefix you have typed. If you type nothing, you get access to every line in the history file.

bindkey '^L' push-input

If you type a command, and then have second thoughts, use control-L rather than control-C to kill the command. Then after you finish the subsequent command, you will get what you typed back again on the following line.


There is a long list of possible zsh environment options. These for the most part are set in exactly the way recommended with the zsh distribution, and these entries are what is distributed with the suggested zshenv. I have moved these here for organizational reasons. The option entries are of the form:

setopt                               \
	append_history               \
	auto_list                    \
	NO_sun_keyboard_hack         \
	unset                        \
	# sh_option_letters          \
	# NO_sh_word_split           \

Notice two things:

  1. Everything is really on one line. The escape (\) is for the newline, so every entry except the very last noncommented entry needs this.
  2. Everything commented out comes after the non-escaped new-line at the end. So if you want to turn one of those that is off on, you need to copy and everything except the # sign and paste it in before the end (i.e., the penultimate position). Better yet, just issue another setopt comand somewhere else further downstream, like within $ZDOT/zshrc_local.d or in the user's ~/.zshrc.

For individual explanations of each option, I am going to refer you to the Comprehensive Manual


Some of the zsh completions we have added require setting up some environment parameters.

open completion

The first of these is an augmented completion function for the Darwin OS X open command . The environment settings responsible for getting this to work are located in 121_environment.completions.additional.zsh.

user and host completion functions

One of the really nice features of zsh is that it allows username and hostname completions, so the ssh command, for example, will let you complete with any known user name and host name.

ssh wg\tab

completes to

ssh wgscott@

and then another poke on the tab key allows me to complete from a list of all known host names. This is very cool, but the catch is that zsh needs to know what users and hosts to use. By default, it gets this information from /etc/passwd and /etc/hosts. But this isn't great, at least on OS X, where /etc/passwd contains all sorts of "user" names like clamav and www. Worse, /etc/hosts is pretty much empty.

The solution is to be able to edit the completion options easily. Wataru Kagawa developed a very nice GUI interface for doing so. This is controlled with two functions:

Please read those pages for more details about how this works, or just issue the commands to see how it works.

Wataru Kagawa has extensively re-written an enhanced completion system for the users and hosts that works with (for example) ssh. The shell code and environment settings required for getting this to work are also located in 121_environment.completions.additional.zsh.


A few additional environment variables are defined for convenience. These are most likely harmless even if they are useless to you. The easiest way to disable them is to reassign them, or unassign them, in $ZDOT/zshrc_local.d, rather than to edit this file.

These variables include:


These variables provide navigational short-cuts specific to Fink on OS X. for example, the first of these allows me to issue

cd $un\tab

and the completion system expands this to

cd $unstablefink

which is the equivalent to typing

cd /sw/fink/dists/unstable/main/finkinfo

Finally, there is a conditional test to check whether an individual user might wish to use the contents of environment.xtal.d/, a set of files I have made for my crystallography colleagues (the original target audience). By default, this is skipped over, in deference to the rest of the user-world. If you uncomment the line


zsh will source the environment.xtal file. By default it does not do so.


Again, most of these settings have been taken directly from the zsh distributed options. There is a lot here. Styles and tags control completion behaviors and other command-line experiences, and can be tailored globally or fine-tuned for individual sets of commands or individual commands. I am going to refer you again to the Comprehensive Manual


A few additional styles are added, mostly those that correspond to completion functions that we created.

There are a few other tweaks, which enhance the user experience. Here's one nice example: If you have a command that has more than 10 (you can change the number) possible completions, tabbing through the list can get tedious, so this gives you a reverse-video selection menu in which you can use the arrow keys to find your choice. This is nice if you have 600 files to choose from, for example:

# enable menu selection
zstyle ':completion:*' menu select=10

Many of these entries are specific to zsh-template supplied functions and programmed completions.

Most people use multiple terminal sessions simultaneously, so we would like to share history between terminal sessions

setopt share_history

Some of the style settings help with completions.

For example, if you issue the command string

open -a wor\tab

you would like it to expand to

open -a Microsoft\ Word

putting in the capital letters and transmogrifying "word" or "Word" into "Microsoft\ Word". The following style does all this:

zstyle ':completion:*:*:open:*' matcher 'm:{a-z}={A-Z} r: ||[^ ]=**'


An interactive login message will be generated with some basic information. Here is a real example:

Time: 23:21  up 5 days, 15:18, 4 users, load averages: 0.28 0.24 0.23 
Initializing zsh version number 4.3.2 

I thought cyan was unobtrusive.


This checks to see if your locatedb is more than two weeks old. If it is, it nags you to update it and to run other system maintenance scripts that usually get run on a periodic daily, weekly, and monthly basis around 3 am if you leave your computer on. This is especially useful on laptops and other machines that get turned off or put to sleep on a regular basis.


This file is obsolete (and is not processed) on 10.5. X11 on 10.5.X now "just works" as if it were an integral part of the operating system. This is a "legacy" shell script that basically sought to do the same thing (make X11 seamless with the operating system) for 10.4 and earlier.



There are five subdirectories in the local-functions directory, in an attempt to organize the functions distributed with zsh-templates. Click on the links to see the most up-to-date listing of the contents.

Functions that begin with _foo are programmed completions for the command foo. (Occasionally there are ancillary completion functions with the underscore prefix as well.)

You can browse an (almost complete) list of functions in the on-line documentation.

Here are the five subdirectories:


These are completions and functions that are unique to OS X. For that reason, most of the functions and completions reside in this directory.


This directory contains shell scripts and other files that are not functions themselves, but that some of the functions need in order to function. The file vim_binary_plist.rc, for example, is read by vim when it encounters a file called foo.plist in binary format. (That file is from Moritz Heckscher).


These are functions and completions that should work on any unix platform (they are not OS X specific, although some have optional features that only work on OS X).


These are functions that might really annoy you or give unexpected behavior. Some do nothing more than put the command name in a terminal menu bar and tab. These are not loaded by default.


These are functions and completions that only crystallographers would find of use.


By default, we use a very simple prompt, defined by the function prompt_simple_setup. You can change the prompt to a number of other themes supplied with zsh, as well as a colorful, elaborate and informative prompt authored by Gary Kerbaugh.

We have made a nice gui interface that is invoked with the function command switch_prompt that makes it easy to select a prompt and then to customize it.

Customizing the Command-line Prompt

The file prompt controls the appearance of the shell prompt. By default, this is


for ordinary users, and


for the root user. Many people want something more elaborate, and zsh makes this easy. There is an associated function command called


that lets you pick from a menu and to change the prompt interactively. The menu gives you the list of zsh-supplied prompts, as well as my "simple" default one, and a very nice one written by Gary Kerbaugh that I have called "kerbaugh". There is also one called "off" that just gives you the percent sign, but it's main function is to clear out residue form some of the more complex prompts if you are switching around.



The contents of this directory are read after those of $ZDOT/zshenv.d and $ZDOT/zshrc.d

Therefore, this is the best directory to put your own files in that modify the environment for the whole system. (Individual user modifications are best placed in ~/.zshrc, which is processed subsequent to the contents of this directory). Often it might be easiest to copy the component file from ../zshrc.d and then edit and modify it here.

See the README file for more information.

You can place any new function shell script in the subdirectory called site-functions. Any shell script placed here will automatically be loaded.

See the README file for more information.

Any file or function with the string "disabled" in the filename will be ignored.

The Manual Pages




the latter are more easily browsed using either [this link or by pointing a Mozilla-style web browser (eg: Camino, FireFox, SeaMonkey) to the directory $ZDOT/man/html on your own machine.

Functional Clusters

Several sets of functions work together in a cluster or program suite. I've created a separate wiki page to describe ZSH Template Function Suites

Return to ZSH on OS X.
Personal tools