5 tips to improve productivity with zsh

The zsh shell offers countless options and features. Here are 5 ways to boost your efficiency from the command line.
314 readers like this.
computer screen

Opensource.com

The Z shell known as zsh is a shell for Linux/Unix-like operating systems. It has similarities to other shells in the sh (Bourne shell) family, such as as bash and ksh, but it provides many advanced features and powerful command line editing options, such as enhanced Tab completion.

It would be impossible to cover all the options of zsh here; there are literally hundreds of pages documenting its many features. In this article, I'll present five tips to make you more productive using the command line with zsh.

1. Themes and plugins

Through the years, the open source community has developed countless themes and plugins for zsh. A theme is a predefined prompt configuration, while a plugin is a set of useful aliases and functions that make it easier to use a specific command or programming language.

The quickest way to get started using themes and plugins is to use a zsh configuration framework. There are many available, but the most popular is Oh My Zsh. By default, it enables some sensible zsh configuration options and it comes loaded with hundreds of themes and plugins.

A theme makes you more productive as it adds useful information to your prompt, such as the status of your Git repository or Python virtualenv in use. Having this information at a glance saves you from typing the equivalent commands to obtain it, and it's a cool look. Here's an example of Powerlevel9k, my theme of choice:

zsh Powerlevel9K theme

The Powerlevel9k theme for zsh

In addition to themes, Oh My Zsh bundles tons of useful plugins for zsh. For example, enabling the Git plugin gives you access to a number of useful aliases, such as:

$ alias | grep -i git | sort -R | head -10
g=git
ga='git add'
gapa='git add --patch'
gap='git apply'
gdt='git diff-tree --no-commit-id --name-only -r'
gau='git add --update'
gstp='git stash pop'
gbda='git branch --no-color --merged | command grep -vE "^(\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d'
gcs='git commit -S'
glg='git log --stat'

There are plugins available for many programming languages, packaging systems, and other tools you commonly use on the command line. Here's a list of plugins I use in my Fedora workstation:

git golang fedora docker oc sudo vi-mode virtualenvwrapper

2. Clever aliases

Aliases are very useful in zsh. Defining aliases for your most-used commands saves you a lot of typing. Oh My Zsh configures several useful aliases by default, including aliases to navigate directories and replacements for common commands with additional options such as:

ls='ls --color=tty'
grep='grep  --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn}'

In addition to command aliases, zsh enables two additional useful alias types: the suffix alias and the global alias.

A suffix alias allows you to open the file you type in the command line using the specified program based on the file extension. For example, to open YAML files using vim, define the following alias:

alias -s {yml,yaml}=vim

Now if you type any file name ending with yml or yaml in the command line, zsh opens that file using vim:

$ playbook.yml
# Opens file playbook.yml using vim

A global alias enables you to create an alias that is expanded anywhere in the command line, not just at the beginning. This is very useful to replace common filenames or piped commands. For example:

alias -g G='| grep -i'

To use this alias, type G anywhere you would type the piped command:

$ ls -l G do
drwxr-xr-x.  5 rgerardi rgerardi 4096 Aug  7 14:08 Documents
drwxr-xr-x.  6 rgerardi rgerardi 4096 Aug 24 14:51 Downloads

Next, let's see how zsh helps to navigate the filesystem.

3. Easy directory navigation

When you're using the command line, navigating across different directories is one of the most common tasks. Zsh makes this easier by providing some useful directory navigation features. These features are enabled with Oh My Zsh, but you can enable them by using this command:

setopt  autocd autopushd \ pushdignoredups

With these options set, you don't need to type cd to change directories. Just type the directory name, and zsh switches to it:

$ pwd
/home/rgerardi
$ /tmp
$ pwd
/tmp

To move back, type -:

Zsh keeps the history of directories you visited so you can quickly switch to any of them. To see the list, type dirs -v:

$ dirs -v
0	~
1	/var/log
2	/var/opt
3	/usr/bin
4	/usr/local
5	/usr/lib
6	/tmp
7	~/Projects/Opensource.com/zsh-5tips
8	~/Projects
9	~/Projects/ansible
10	~/Documents

Switch to any directory in this list by typing ~# where # is the number of the directory in the list. For example:

$ pwd
/home/rgerardi
$ ~4
$ pwd
/usr/local

Combine these with aliases to make it even easier to navigate:

d='dirs -v | head -10'
1='cd -'
2='cd -2'
3='cd -3'
4='cd -4'
5='cd -5'
6='cd -6'
7='cd -7'
8='cd -8'
9='cd -9'

Now you can type d to see the first ten items in the list and the number to switch to it:

$ d
0	/usr/local
1	~
2	/var/log
3	/var/opt
4	/usr/bin
5	/usr/lib
6	/tmp
7	~/Projects/Opensource.com/zsh-5tips
8	~/Projects
9	~/Projects/ansible
$ pwd
/usr/local
$ 6
/tmp
$ pwd
/tmp

Finally, zsh automatically expands directory names with Tab completion. Type the first letters of the directory names and TAB to use it:

$ pwd
/home/rgerardi
$ p/o/z (TAB)
$ Projects/Opensource.com/zsh-5tips/

This is just one of the features enabled by zsh's powerful Tab completion system. Let's look at some more.

4. Advanced Tab completion

Zsh's powerful completion system is one of its hallmarks. For simplification, I call it Tab completion, but under the hood, more than one thing is happening. There's usually expansion and command completion. I'll discuss them together here. For details, check this User's Guide.

Command completion is enabled by default with Oh My Zsh. To enable it, add the following lines to your .zshrc file:

autoload -U compinit
compinit

Zsh's completion system is smart. It tries to suggest only items that can be used in certain contexts—for example, if you type cd and TAB, zsh suggests only directory names as it knows cd does not work with anything else.

Conversely, it suggests usernames when running user-related commands or hostnames when using ssh or ping, for example.

It has a vast completion library and understands many different commands. For example, if you're using the tar command, you can press Tab to see a list of files available in the package as candidates for extraction:

$ tar -xzvf test1.tar.gz test1/file1 (TAB)
file1 file2

Here's a more advanced example, using git. In this example, when typing TAB, zsh automatically completes the name of the only file in the repository that can be staged:

$ ls
original  plan.txt  zsh-5tips.md  zsh_theme_small.png
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   zsh-5tips.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git add (TAB)
$ git add zsh-5tips.md

It also understands command line options and suggests only the ones that are relevant to the subcommand selected:

$ git commit - (TAB)
--all                  -a       -- stage all modified and deleted paths
--allow-empty                   -- allow recording an empty commit
--allow-empty-message           -- allow recording a commit with an empty message
--amend                         -- amend the tip of the current branch
--author                        -- override the author name used in the commit
--branch                        -- show branch information
--cleanup                       -- specify how the commit message should be cleaned up
--date                          -- override the author date used in the commit
--dry-run                       -- only show the list of paths that are to be committed or not, and any untracked
--edit                 -e       -- edit the commit message before committing
--file                 -F       -- read commit message from given file
--gpg-sign             -S       -- GPG-sign the commit
--include              -i       -- update the given files and commit the whole index
--interactive                   -- interactively update paths in the index file
--message              -m       -- use the given message as the commit message
... TRUNCATED ...

After typing TAB, you can use the arrow keys to navigate the options list and select the one you need. Now you don't need to memorize all those Git options.

There are many options available. The best way to find what is most helpful to you is by using it.

5. Command line editing and history

Zsh's command line editing capabilities are also useful. By default, it emulates emacs. If, like me, you prefer vi/vim, enable vi bindings with the following command:

$ bindkey -v

If you're using Oh My Zsh, the vi-mode plugin enables additional bindings and a mode indicator on your prompt—very useful.

After enabling vi bindings, you can edit the command line using vi commands. For example, press ESC+/ to search the command line history. While searching, pressing n brings the next matching line, and N the previous one. Most common vi commands work after pressing ESC such as 0 to jump to the start of the line, $ to jump to the end, i to insert, a to append, etc. Even commands followed by motion work, such as cw to change a word.

In addition to command line editing, zsh provides several useful command line history features if you want to fix or re-execute previous used commands. For example, if you made a mistake, typing fc brings the last command in your favorite editor to fix it. It respects the $EDITOR variable and by default uses vi.

Another useful command is r, which re-executes the last command; and r <WORD>, which executes the last command that contains the string WORD.

Finally, typing double bangs (!!) brings back the last command anywhere in the line. This is useful, for instance, if you forgot to type sudo to execute commands that require elevated privileges:

$ less /var/log/dnf.log
/var/log/dnf.log: Permission denied
$ sudo !! 
$ sudo less /var/log/dnf.log

These features make it easier to find and re-use previously typed commands.

Where to go from here?

These are just a few of the zsh features that can make you more productive; there are many more. For additional information, consult the following resources:

An Introduction to the Z Shell

A User's Guide to ZSH

Archlinux Wiki

zsh-lovers

Do you have any zsh productivity tips to share? I would love to hear about them in the comments below.

Avatar
Ricardo Gerardi is Technical Community Advocate for Enable Sysadmin and Enable Architect. He was previously a principal consultant at Red Hat Canada, where he specialized in IT automation with Ansible and OpenShift.

4 Comments

Nice article, I'm definitely gonna give zsh a try.

Switched from bash to zsh in the mid-90s, never looked back. This was way before Oh My Zsh, though, so I've hand-crafted most of my setup. Time to refactor and maybe leverage Oh My Zsh.

My most useful settings, though:

setopt ignore_eof nobeep
bindkey -s '^X^X' '^Uexit\n'

On a slow SSH connection, it's possible to accidentally hit Ctrl-D once too often when editing the command line (Emacs mode), and so I mapped my exit sequence to be Ctrl-X Ctrl-X. And "nobeep" is a given.

For working long time is hard and we need find some smart ways that can Increase the number of work we will do. very effective post. Thanks

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.