We compare the Bash, Zsh, and fish shells


All shells let you combine several commands into one function. As Listing 2 shows, Bash and Zsh use an identical syntax, whereas fish again goes its own way.

Listing 2


# Bash and Zsh
saywhat() {
  echo "Hello!"
# Bash and Zsh (alternatively)
function saywhat {
  echo "Hello!"
# Fish
function saywhat
  echo "Hello!"

Access to a variable only works in the context in which you defined it. If you use Bash or Zsh, only those variables that you explicitly mark as local are local:

local name = "Peter

Zsh also supports anonymous functions that have no name. Such a function is immediately executed by the shell as soon as it stumbles upon its definition in the code. This can be used, for example, to restrict the visibility of variables in start scripts to the body of the function.


Zsh and fish can automatically reload functions used by a script from separate files. However, this autoload mechanism differs slightly in the two shells.

For example, in Zsh you first need to explicitly register the corresponding functions with the autoload keyword. This shell also lets you extend the range of functions using modules, which you can even load at runtime if required. Some of these are already provided by the shell: For example, the zsh/zftp module adds a full FTP client.

Using the built-in compile command, Zsh can compile functions and scripts and store them in a binary file. The results are loaded faster then, but they are not available in other shells.

Configuring Zsh

The best way to try out fish is through the online browser interface [6] or by running the fish_config utility and exploring the graphic configuration utility. With Zsh, you'll also want to install it and experiment before deciding to migrate.

Zsh has one thing Bash doesn't have: a handy configuration menu that appears when you start the shell for the first time. Zsh looks for the configuration files, and if it can't find them (in other words, if you haven't configured the shell yet), the config menu launches (Figure 4). Press 1 to enter the main menu (Figure 5).

Figure 4: The start menu invites you to configure Zsh settings.
Figure 5: The Zsh configuration main menu.

When you get to the main menu, press 1 to set the scope of the history. You can enter the number of lines of history you would like to retain within the shell, select a file for saving the history, and choose how many lines you would like to keep within the file. In the example shown in Figure 6, the history has been extended to 10,000 lines.

Figure 6: Command history settings.

Enter   to save and return to the main window, or enter q to return without saving.

Back in the main window, press 2 to go to the autocomplete settings. You can choose between the default autocomplete options (1) or run a configuration tool that will let you customize the autocomplete settings (2). Choose 3 if you don't want to use autocompletion.

Item 3 in the main menu lets you set the keyboard behavior in the shell's line editor. You can get the editor to behave like either of the classic Unix editors Emacs or vi. It is best to leave the suggested value.

Item 4 in the main menu lets you configure some other common shell settings (Figure 7), including settings related to pattern matching, command history, and whether to beep on errors.

Figure 7: Configuring additional Zsh settings.

When you're finished with the configuration menu, you can save the settings by pressing   in the main window. The new settings will take effect immediately.

An example of a Zsh feature with lots of room to customize is the command prompt. The developers have invested considerable energy into command prompt options. Customizing the string of text that appears before you enter a command might seem like a random personal choice, but many admins use the prompt for orientation and documentation purposes. For instance, including the date and time on a prompt means that a screenshot will document exactly when the command was run.

Use the following commands in Zsh to load the preconfigured prompt options:

autoload -U promptinit

After you enter these commands, you can list the available prompt themes with prompt -l. To see what they all look like, enter prompt -p (Figure 8).

Figure 8: Displaying prompt patterns.

Note that the two-line prompts in Figure 8, which show the prompt above the actual command line, add clarity for situations where the prompt is providing essential information for the user. After you set the prompt interactively with:

prompt -s pattern_name

a hint appears telling you that, for a permanent change of the prompt, you have to enter the pattern in ~/.zshrc. The entry in .zshrc is similar to what you just did at the command line (Listing 3).

Listing 3

Changing the Prompt

autoload -Uz promptinit
prompt pattern_name

The Zsh configuration files are shown in Table 1. The names in Table 1 refer to the files in the user's home directory. Global files with the same names (but without the leading dot) are found in /etc.

Table 1

Zsh Configuration Files

File Name



Login settings and commands


Settings that apply regardless of how the shell is called


Shell startup settings and commands


Commands for logging in


Commands for logging out of a session

Zsh processes the configuration files in the order .zprofile, .zshrc, and .zlogin when you log in. Use the .zshenv file to configure settings that apply regardless of how the shell was started. When called manually, Zsh only evaluates .zshrc and .zshenv. When logging out of the session, the commands from .zlogout are executed.

Note that the .zlogin and .zlogout config files make it possible to facilitate tasks by creating specially tailored user accounts, for example, for data backup, batch jobs in remote data transmission, or system maintenance. In this way, you can even delegate tasks to nonexperts, because all they have to do is log on, and the task executes automatically. Placing exit in the startup file automatically logs the user off after the task is completed.

If you don't like the predefined prompt themes provided with Zsh, you can design your own prompt. Like other personal settings for interactive sessions, prompt design details go in .zshrc. Setting up your own prompt basically works like it does in Bash, and even the escape sequences for the colors are the same [4], but you need to initiate them in Zsh using \e. The placeholders you use to build the prompt content, on the other hand, are completely different from those for Bash (see Table 2). For more information, refer to the Zsh manual [2].

Table 2

Zsh Prompt







Host name without domain


Full computer name


User ID


Exit code of last command


Current directory


Current directory

%~ (truncates the home directory specification)

Sequence number in history


Variables and aliases are entered in the .zshenv file. In our test, the usual colors for directories, executables, and so on were not output by the ls command; I corrected this with the following line:

alias ls="ls --color"

Any additional variables and $PATH extensions work like in Bash and need to be added to .zshenv.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Command Line: Fish

    The fish shell provides many features that rival the well-known Bash. We examine some highlights.

  • Fish Shell

    The Fish shell offers some user-friendly features for command line beginners.

  • Bash Builtins

    Even beginners can benefit from a greater understanding of the Bash shell’s many builtin commands.

  • Command Line

    A few basic tricks can liven up the command line and add a dash of color to your console.

  • Bash vs. Vista PowerShell

    Microsoft’s new PowerShell relies on .NET framework libraries and thus has access to a treasure trove of functions and objects. How does PowerShell measure up to traditional shells like Bash?

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More