Zero to Z-Shell: Learn what all the fuss is about with Z-Shell
by Noah Gift
By and large, most Red Hat Linux systems will have Bash as the default shell. Bash is a darn great shell, but this article is about another equally great shell, called Z-Shell, that has most of the attributes of Bash, but in some cases goes the extra mile to give you the flexibility to customize your shell more than Bash allows.
This article is somewhat advanced, but if you’re very patient, with some effort, you will do just fine. Remember to make small changes, test them, and then make more small changes, test, and repeat.
First a few basics. I would encourage you to fire up a shell and test out this code while you read.
Basic configuration and setup
Switching your default shell to zsh
Before you start hacking away and changing config files, you need to do a few things first. Since Bash is the default shell, you will need to change things to Z-Shell, at least temporarily, while you follow this article. By far the easiest way to change your shell is to use the chsh command.
To quickly change to zsh, issue this command:
chsh -s /bin/zsh
If you take a peek at your /etc/passwd file:
less /etc/passwd
You will see that the default shell for your user account has been changed. This is a permanent change, and when you log back in again you will stay with the zsh.
Z-Shell Configuration Files
The good and bad of it is that zsh can have as many as eight different configuration files. This is the order of execution that you should know about for the most common files:
1. /etc/zshenv - Always executed global configuration file.
2. ~/.zshenv - Local configuration file.
3. /etc/zprofile - Global Login shell configuration.
4. /etc/zshrc - Global interactive shell configuration.
5. ~/.zshrc - User interactive shell configuration.
The most efficient file to edit is probably ~/.zshenv as it will configure both interactive and non-interactive shells. For all of the examples I show below, please edit the ~/.zshenv file.
Backing up your configuration files or using version control
One thing I always caution is to backup your original file or use version control. One of the absolute worst situations to be in is with a damaged configuration file and no way to return to the original state. Make a backup of any file you edit, or better yet, use version control!
Z-Shell Cookbook
Since there are so many things you can do with Z-Shell and no way to talk about them all, I’m going to give you as much as possible through a cookbook format. I will go through the “recipes,” and you can “cook” along with your shell at home. Did you you remember to make a backup of your original files? Great, lets get started!
Autocompletion
Z-Shell has incredible autocompletion tools. Here are few barebones examples:
In order to use autocompletion, you will need to put the following in your ~/.zshenv file:
#Allows prompt profiles autoload -U promptinit promptinit
With zsh you can autocomplete things other than just file. If you type in:
$PA
you get variable completion.
If you use something like gunzip in a directory with .gz files it will just figure out what files it should work with if you keep selecting tab. Try it out.
If you’re in the mood to get really geeky, check out completion functions in zsh. I don’t cover them in this article, but they are worth investigating.
Command history and history substitution
Mastering the use of command history will save you many keystrokes!
Remove mistakes:
root@cent]~# lesss /var/log/messages zsh: command not found: lesss [root@cent]~# ^s less /var/log/messages
Remember commands:
[root@cent]~# ls /var/log/messages /var/log/messages [root@cent]~# !! ls /var/log/messages /var/log/messages !$ Last Argument on the previous command line cp !$ . (copies /var/log/messages to current directory)
Rerun previous commands:
!l root@cent]~# !l ls /var/log/messages /var/log/messages
This works because ls is in the history.
Finally, you can substitute by a command line number.
[root@cent]~# !32 ls /var/log/messages /var/log/messages
Key bindings
Key bindings literally bind things to certain keys. Instead of using readline like Bash, zsh uses Zsh Line Editor or zle. In Bash you use bind and in zsh you use bindkey.
In zsh to find out what keys are bound:
bindkey -L
To see the whole list of editor commands that can be bound, and it is huge:
zle -la
I would recommend exploring keybindings by piping the list of your currently bound keys to less:
bindkey -L | less
Job Control
An example of using job control in Z-Shell:
tail -f /var/log/messages & jobs kill %1 run:
If you have a long-running process, you might want to let it work in the background while you continue other things. For example, if you download a tool I wrote called Liten, you may want to run it as a background job, as it will search a directory tree and do md5 checksums on files to find duplicates. This may take quite a while to completely get through a large file system, so it’s a perfect choice to run in the background.
Go ahead and run liten on your home directory as a background process:
./liten.py $HOME
Then click Ctrl+Z to send the job to the background.
The output will be:
zsh: suspended ./liten.py $HOME
Then run:
jobs
And the output will be:
[1] + suspended ./liten.py $HOME root@cent]~# bg %1 [1] + continued ./liten.py $HOME
If you have only one suspended job, you can use the shortcut:
%top %vi
You can also set an option in zsh to resume jobs by name:
setopt auto_resume
This lets you resume a job just by typing in the name of the job. It’s quite handy!
Remember that if you put a job in the background, you might want to pipe stdout somewhere while it runs.
When you exit the shell and you have a running job, zsh will kill the jobs by giving them a SIGHUP signal. Here are ways to tell zsh to prevent killing the jobs on exit:
- Use
nohupin front of jobs you want to run on exit. Make sure it used in this manner:nohup top &
- You can also let your job run wild and give it the disown command or followup the the job with
&!.
Priority of background jobs
In zsh, background jobs are automatically given a lower priority unless you set an option.
Process substitution
One neat feature zsh has is the special =(…) substitution.For example, if you want to find out the full path to a program you can do run:
ls =top
The output will be:
/usr/bin/top
I personally think this shorthand is quite nice, and I commonly find myself needing to find the full path to some command.
Another example would be when you want to use a shell command to format stdout and then
edit it in a text editor like vi:
vim =(tail < /var/log/messages)
Customizing Prompt
Like just about everything else in Z-Shell, the prompt is extremely customizable. If you would like to check out a few of the themes, you can set your .zshenv to allow prompt switching:
#Allows prompt profiles autoload -U promptinit promptinit
You can now view available prompt themes by typing:
prompt -l
You can also select and then set with the following:
prompt oliver prompt -s
You will get back something like this:
prompt -s oliver Set and save not yet implemented.
Please ensure your ~/.zshrc contains something similar to the following:
autoload -U promptinit promptinit prompt oliver
If you want to get really fancy, you can also edit the following in your .zshenv file:
#Customize Prompt PROMPT=$'[%n@%m][H:%B%!%b][J:%B%j%b]> ' RPS1='[D:%B%~%b]'
This is actually my current prompt, but feel free to tweak it around a bit; that’s how you learn. I won’t go any more into the details of customizing prompts here, but you should read through the Z-Shell manual.
File and directories
If you set:
setopt autocd
It will allow you to cd into a directory without typing cd first.
If you set:
cdable_vars
It will allow you to cd to a variable, such as:
cd HOME
Shortcuts for referring to directories
Get back to the directory you were just in:
~- same as $OLDPWD
Some fancy stuff:
~2 Second directory on the directory stack.
~-0 Final directory on the directory stack.
This works in conjunction with the pushd and the popd commands, which I won’t get into in this article, but you can read more here.
Using braces
Create ten test files in a few keystrokes:
touch {1..10}.txt
Summary
Z-Shell is a mind-blowing shell with the ability to tweak and change just about anything. What I covered in this brief survey article barely does Z-Shell justice. If you are interested in knowing more about Z-Shell or Bash, I would highly recommend reading, From Bash To Z-Shell by Oliver Kiddle, Jerry Peek, and Peter Stephenson. It is truly a masterful book! Of course, you can’t go wrong by reading the official documentation either.
Finally, I would love to hear back on some extra tricky things you have done with your Z-Shell.







October 11th, 2007 at 10:58 pm
Actually I have tried to work with both ZSH and Bash. I have to admit that I am more comfortable with bash. The one thing no one seems to compare is the bash-completion package available via most distros. This creates quite a large autocompletion feature that is oft overlooked. With bash-completion I can autocomplete hosts listed in my ~/.ssh/known_hosts file. I.E. ssh root@haiku.flabbergasted.com
I was unable to get this feature working in zsh.
Cheers,
Duffie Cooley
October 12th, 2007 at 1:37 am
“Learn what all the fuss is about with Z-Shell”
.. what fuss??
October 15th, 2007 at 2:26 am
i have configure a linux server so pl. send me detail i have a condigure both server like mail server and web server and data server ftp & telnet & ssh & scp & samba server file server and data server so pl. help me how to configure both server in linux and client is windows i have waiting for mail and solution pl. mail me.
October 24th, 2007 at 11:37 am
Well, the good thing with zsh is that is can use bash completion… It has an emulation mode.
So in the end it is impossible for bash to get more completion than zsh, because zsh already has a big base.
Not comparing quality here, just saying. ;-)
December 13th, 2007 at 3:12 am
I tried zsh and although its capabilities are impressive, even in the recent version (on FC6) I had terrible problems with UTF-8 support (or rather non-support) in zsh. I got couple of file names with diacritic in their names badly mangled by zsh. Nice as it seems to be, this is showstopper for me (being Czech, diacritic happens even in the file names — think automatically generated names of .ogg files).