30 Jan 2012

Terminal Heaven Part 3: zsh and oh-my-zsh

Posted on January 30, 2012

In the last and final part of this series I will write about a part of my toolset which made my daily work with the command line a lot more productive then before: the zsh shell and especially oh-my-zsh which is a configuration system for zsh.

I’m working with Unix shells for a long time now and have always been a fan of the bash shell. Sometimes I tried one of the other shells to see if they are better suited for my needs but after a short time I always returned to the good old bash. I even tried the zsh shell once but the feature set is so overwhelming and the learning curve was so steep that I gave up on this very quickly.

Reading a lot about oh-my-zsh made me giving the zsh shell another try. One of the biggest problems in starting using zsh is that the default configuration is not very usable and you will have to spend countless hours before you have a usable setup for yourself. oh-my-zsh fixes this by providing a useful default configuration from the start and it also gives you a lot of plugins and themes which are all provided by an active and growing community.

I won’t provide a tutorial of how to use zsh here but I will show you some features which are my personal highlight of my zsh/oh-my-zsh setup.

Directory Navigation

One of the things you will do the most when you are working on a shell is changing directories. zsh can help you in multiple ways doing this. For example:

  • zsh tries to fix your typos
  • no need for the “cd” command
  • Typing “/App/Saf+<TAB>” will expand the path to “/Applications/Safari.app”
  • The “d” command gives you a list of the last used directories and you can change to each dir by just typing a single number (1 is always the previous dir)

I also defined “p” as a directory alias for my project directory which gives me the possibility to just type “p/code+<Tab>” to expand the path to the directory of this website and a single press of return will change the path to this directory.

Customizable Prompt

oh-my-zsh provides a lot of themes you can use to customize the shell to your own liking. I’m using the “fishy” theme though it’s not that fancy but the prompt is exactly how I want it to be. It looks like this:


On the left you see the usual stuff like logged in user and the current path. On the right side you can see the current git branch and status of my project.


Globbing helps you selecting files matching a specific pattern. The zsh globbing is very powerful and everybody should try to learn at least the basics of this feature.

The following example selects all png files recursively and copies them to the backup directory:

> cp **/*.png backup

Command Arguments Completion

With the command arguments completion it is not necessary anymore to remember all command line options of a shell excecutable. For example if you enter the following:

> ls -<TAB>

You will get:

-1                        -- single column output
-A                        -- list all except . and ..
-B                        -- print octal escapes for control characters
-C                        -- list entries in columns sorted vertically
-F                        -- append file type indicators

This kind of completion is available for a lot of commands like git, svn, brew. The completion is very powerful and it also works for git branch names or it substitutes a process name with the process id when used with the kill command.

search-history plugin

The search-history plugin is the most powerful oh-my-zsh plugin. It basically provides a substring search in your zsh command history. To activate it just add the following line to your “.zshrc” file:

source $ZSH/plugins/history-substring-search/history-substring-search.zsh

From now on it is very easy to get an old command from your history. You can type in any text and use cursor up and down to scroll to all matching history entries. For example if I want to update my homebrew installation, I just type “out” followed by cursor up and most of the time the next matching entry is “brew update && brew outdated”.

The End

I hope I could provide you some ideas for your own setup of your shell environment. For me this setup works like a dream and makes it really fun and easy to work on the console. No matter how good the modern GUIs are, using the shell is sometimes still the best and fastest way to go.