ZSH

One of the great things about linux is that you have flexibility to choose. The standard shell for most Linux systems is bash. Zsh is one of the alternative shells, and requires a brief history lesson to understand where it came from, and why it's different from bash.

A brief history of shells

This may not be chronologically accurate, or even accurate at all

Back in the early days of UNIX there was one shell, the Bourne Shell (not to be confused with the Bourne movies that are rather good. Rather named for the guy who came up with it). The Bourne Shell is often referred by it traditional command sh (all contained in /bin/sh). The Bourne shell has it's own syntax for writing scripts and working in the shell, but it wasn't really related to anything. So someone came up with the great idea to make a shell that used C style syntax (as per that is UNIX's native language), this is the C shell. (/bin/csh) It had a number of improvements for basic shell use, but it turned out that for some other uses it didn't work as well. Down the road someone improved upon csh, a shell called tcsh. Back to the Bourne shell however, another shell came from it, the Korn shell (/bin/ksh), the Korn shell had some improvements, but wasn't as widely used. During this time the GNU project decided that they needed a free shell, so they made the Bourne Again shell (/bin/bash). This is your standard shell in Linux, and is quite powerful, also /bin/sh is usually just a link to /bin/bash in Linux. Another shell exists that is more modern, and that is zsh, which is partially derived from the Korn shell, also takes some things from the C shell and also the Bourne shell (and bash for that matter).

What makes zsh different

zsh takes some of the best features ksh, bash, csh, and sh. But it doesn't emulate any of them (by default). You can start zsh in sh or ksh emulation mode if you want, and pass options to emulate bash. If you were to run zsh right now by running the command:

$ zsh

You probably can get by just fine without any hassle. To get zsh tweaked the way you might have bash, or to take advantage of the cool options of zsh, you'll have to do a little more.

Basic usage of zsh

If you're familiar with working in a bash shell, you should get around just fine. There are some features that you should take note of that are different.

  • $ !! - executes the last command (from csh)
  • <TAB> - tab completion, hit tab after you tab a command, part of a command, part of a word after the command, most times actually, it'll complete or give you a list of options. Try it out by typing cd, then hit tab. You should see a list of directories. If you start typing the directory and hit tab to have zsh finish the word for you. You can also tab complete options for some programs (mplayer and others).
  • syntax for shell scripts: handles all basic sh scripts and has more features unique to it.

CONfiguring zsh

zsh has a handful of configuration files, and you'll probably only need to set one. If you edit these files and want to test it without restarting the shell, you can just . ./.zshrc

*.zshenv:This file is always run first. You should not put anything in here unless you need it whenever zsh runs anytime. So in general don't use this file
*.zprofile:This is run at login in just like .bash_profile
*.zlogin:This is also run at login, the order of login and profile is constant, if you can figure it out
*.zshrc:This is your basic settings for your shell, and it is this file we'll spend the rest of the time discussing how to configure it.

What to configure

Our local bash doc covers a number of items that don't really change: environment variables, PATH, CLASSPATH, and aliases. One thing to note is that when setting variables you cannot have a space between the equal sign and everything else, for example:

HOSTNAME='my machine'

Setting the Command Prompt

You'll see the prompt a lot so you might want to change it. The default prompt is this:

PROMPT='[%n@%m]%~%# '

The % is the escape character for the prompt in zsh, and if a character follows it, it actually is a special command. For example, the default prompt will look like:

[user@apple]~%

If you start up zsh. So lets explain what these escape sequences are, and how to use them.

%n:your user name
%m:the short machine name (apple if on apple)
%M:the full machine name (apple.cs.byu.edu if on apple)
%/ %d:PWD (print working directory) This can be restricted by part*
%~:same as above, but if in your home directory, will print a '~' instead
%C:PWD, with only the trailing component (same as %1/)
%c:same as above but equivalent to %1~
%#:normal user: prints '%', super user: prints '#', equivalent to (!.#.%)
%N:name of script, sourced file, or shell function that zsh is currently running
%D:the date in yy-mm-dd
%T:current time of day in 24-hour format
%t %@:current time of day in 12 hour am-pm format
%*:current time of day, 24 hour, with seconds
%w:date in day-dd format
%W:date in mm/dd/yy
%(x.true.false):
 if x is true do true else do false
%%:a '%'
%):a ')'

right hand prompt

zsh has the ability to display things on the right hand side of the terminal/console. You can do the same things as with the prompt, and you don't have to worry about typing over it, or it messing up your commands. The variable to set is RPROMPT. For example, to always show the exit code of the last command:

RPROMPT='%?'

colors

For colors you'll first have to have your PROMPT setting look like this: PROMPT=$'%n ' the $ is very important. Colors require basic escape strings, so the basic format for colors is:

%{\e[1;31m%}

This will set all the prompt that follows to ASCII color 31 (red). The basic colors are:

  • 00 default
  • 31 red
  • 30 black
  • 32 green
  • 33 yellow
  • 34 blue
  • 35 purple
  • 36 cyan

At the end of any prompt string put: %{\e1;00m%} to clear the colors.

zsh options

zsh has many options that you can set in your .zshrc. The main source of information on these is: man zshoptions. We'll just be listing a few. You can set options like so: setopt AUTO_CD, and unset like this: unsetopt AUTO_CD in your .zshrc.

  • AUTO_CD - if the command given can't be executed, and the command is the name of a directory, cd to that directory
  • AUTO_PUSHD - whenever you cd to a directory, push it onto the directory stack. You can then pop off the stack with popd
  • BASH_AUTO_LIST - you have to hit <TAB> twice to see the list of options
  • BEEP - (default) beep on error
  • CORRECT - try to correct the spelling of commands.
  • CORRECT_ALL - try to correct the spelling of all arguments in a line
  • DVORAK - use the Dvorak keyboard for the basis for examining spelling mistakes
  • PUSHD_IGNORE_DUPS - don't push multiple copies of the same directory onto the directory stakc
  • RM_STAR_SILENT - do not ask the user before executing a rm with a * in it.
  • RM_STAR_WAIT - waits 10 seconds before executing a rm command with a * in it.

alternate keymaps

zsh has support for vi style command line editing and emacs style command line editing (see man zshzle). These are accessed through the bindkey command. To turn on vi emulation put this line in your .zshrc:

bindkey -v

vi mode in zsh is not vim! It is traditional vi This will let you use vi keys on the command line. (command mode and insert mode, etc). zsh uses the emacs keymap by default, but if you want to ensure it put this line in your .zshrc:

bindkey -e

You can also edit your keymaps to meet your preferences. I for one dislike a purely traditional vi mode, and enjoy being able to backspace over everything. I add these lines to my .zshrc:

bindkey -M viins '^?' backward-delete-char
bindkey -M viins '^H' backward-delete-char

Please note that ^? and ^H are both literal ctrl-? and ctrl-H respectively. To get these you need to be in vim's insert mode and type: ctrl-v ctrl-? or ctrl-v ctrl-h. The -M in this command tells zsh to modify the selected keymap (viins - vi insert mode). You can also bindkeys so they work in all cases:

bindkey '^[[7~' beginning-of-line

Sets, for me, Home to go to the begining of the line. In this case it is not a literal ^[, but I found the key by using ctrl-v <HOME> in vim.