Every day that I program I use the shell and I think most of the developers use it daily. Still often it’s not something which is talked about during education or conferences. This is kind of weird, because from my experience a shell is something that can boost your productivity by a lot. For me the shell is something which I slowly gain knowledge on and acts as a Swiss Army Knife to get many things done on my computer. In this post I’m going to show some of the things which boosts my daily productivity by using a shell.

What actually is a shell?

The terms shell, command line, console and terminal are often interchangeably used, so what actually are they? The latter three I think depend on the operating system you are using, but they all are the same. They are an graphical user interface (GUI) to take input and show output in the form of pure text. The shell is the engine running in the GUI, which translates the input to actual commands and executes these. The result is returned to the GUI and shown to the user. On MacOS and Linux the GUI is called Terminal and on Windows it’s called Command Line (cmd) and recently there’s also a Terminal. The Windows Terminal is relatively new and really makes Windows interesting for a developer to use. With Windows Subsystem Linux 2 (WSL2) on Windows it’s possible to also run native Linux shells on Windows. The most popular shell on Windows is Powershell, which you get out of the box with a Windows installation. On Linux the most popular shells are sh, Bash and ZSH. By default on an Ubuntu intallation the shell Bash is used.

Which shell to use?

For a long time I have been using Bash, since it’s often the default shell. Already a lot is possible with it, but after some time I switched to ZSH and it’s plugin Oh My Zsh. It has many more small, extra features over Bash. They really prove their worth if you are used to them. Of course there is also sh, but it’s the most basic shell, so I wouldn’t recommend using it unless size and compatibility matters. Since I’m used to ZSH and I think it’s better than Bash, I’ll be showing how thinks work in ZSH. Some things are also possible in Bash, but are slightly different, for example the name of the configuration file (.bashrc instead of .zshrc).

Shell customization

With a shell you get a lot of things out of the box, but I think the real power is customizing them to your need. You can do this by changing the .zshrc file located in your home folder. Every time the shell is launched, this file will be executed. I recommend to install Oh My Zsh, which already adds a lot of useful customization which the default ZSH doesn’t provide.

After installing this, it’s time to add configuration specifically for you tasks:

  • If want to call a binary from everywhere on the system, you can add the folder to your PATH:
    export PATH=$HOME/Tools/hashcat-6.2.1:$PATH
    
  • If you execute commands a lot of times and don’t want to type them out every time or search through your history:
    # shortcut to clean docker containers
    alias drm="docker rm -f $(docker ps -aq)"
    # shortcut to go to my directory where my projects are located
    alias projects="cd ~/Projects"
    # shortcuts for all projects to open them in VS Code
    # the name of each folder can be typed to open them straight away in VS Code
    for f in ~/Projects/*; do
      alias $(basename $f)="code $f"
    done
    

Shell expansions

Commands sometimes get more complex than just some cd and ls and for this expansions are often useful. Here Bash and ZSH differ quite a bit. ZSH has the following interesting expansions:

  • Brace expansion: curly braces can be used to execute the same command with different parameters. For example:
    touch my_file.{json,xml}ls
    my_file.json  my_file.xml
    
    ➜  echo {1..5}" apple(s)"
    1 apple(s) 2 apple(s) 3 apple(s) 4 apple(s) 5 apple(s)
    
  • History expansion: allows the re-use of commands in the history of the shell. For example:
    touch /usr/local/test
    touch: cannot touch '/usr/local/test': Permission denied
    # rerun the previous command as sudo:sudo !!
    # no error, which means the file is created
    

ZSH over Bash

On this page there are many advantages of ZSH over Bash. I think these are the most important which help me every day:

  • History substring search: if you type docker and use your arrows to go through the history, only the commands which start with docker are shown. In Bash doesn’t have such a prefix filter and you’ll have to go through all your commands, also commands which don’t start with docker.
  • Suffix aliases: ZSH allows adding aliases to open specific files, for example alias -s json='code' makes sure all JSON files are opened using VS Code.
  • Syntax highlighting: shows whether the typed command is valid, green for valid and red for invalid
  • Auto complete commands: auto completion of specific commands, for example the kill command.

Conclusion

These are some very concrete tricks, but I think the underlying way of working is more important. A good programmer doesn’t want to do any manual work if it can also be done automatically, since this would often save a lot of clicking. A senior programmer will often use the shell for a task, while a junior programmer will still click through the file browser or a program to get things done. It sometimes hurts me a little bit when I see people struggling with an UI, while a shell could achieve their action so easily. It’s often not the question whether an action can be done by a shell, but how it can be done via a shell. So I think the mindset of trying to automate tasks is more important than knowing all the tricks, if you have the right mindset you’ll get there.