Shell in a nutshell
Tags: shell, bash, linux, tutorial
Published: 2023-02-11 08:35:14

---
title: Shell in a nutshell
published: true
description: Tutorial for Shell scripting
tags: shell, bash, linux, tutorial
canonical_url: https://tomdeneire.medium.com/dev-101-shell-in-a-nutshell-42ec8a24e2c5
---


![Photo by [Jonas Dücker](https://unsplash.com/@jonasduecker?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://cdn-images-1.medium.com/max/8000/0*Yxd_yyysX4QWrZaY)
Photo by [Jonas Dücker](https://unsplash.com/@jonasduecker?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

In [another blog](https://medium.com/analytics-vidhya/dev-101-terminal-velocity-8cbf6f132748), I explained the concept of the *shell* — a command language interpreter that executes commands read from standard input, a command line string, or a specified file.

This means that shell can be used either interactively via the terminal:

    tdeneire@XPS-13-9370:~$ sh
    $ echo "hello"
    hello
    $ exit
    tdeneire@XPS-13-9370:~$

or as a CLI:

    sh -c "echo $(date)"

or to execute Shell scripts, saved as .shfiles like this:

    #!/bin/sh

    echo "Hello world"

You can then execute them with `sh myfile.sh`.

Especially the last option is a fantastic tool for writing scripts for automation, installation, configuration, and so on.

Because knowing your way around Shell scripts is a vital tool for any developer working with UNIX systems, I will try to summarize Shell syntax below.

I’ve taken care to limit this summary to “pure” UNIX shell syntax, i.e. the Bourne shell or sh . Most Unix-like systems contain the file /bin/sh that is either the Bourne shell, or a symbolic link (or hard link) to a compatible shell (e.g. dash). The reason for sticking to sh is that different shell versions (bash, dash, ksh, zsh, …) all come with different features, although they are mostly sh-compatible. By sticking to sh syntax you allow your scripts to be executed by a variety of shells, which makes them dependable and robust.

## Hello world

    echo "Hello World!"

## Comments

    \# This is a comment

## Variable assignment

    NAME_1="Tom"    # set
    readonly NAME_1 # read-only
    unset NAME_1    # unset

## Quoting (strong vs weak)

*Quoting variables prevents word splitting and glob expansion, and prevents the script from breaking when input contains spaces, line feeds, glob characters and such.*

    $ echo '$HOME'
    $HOME
    $ echo "$HOME"
    /home/tdeneire

## Arrays

    \# POSIX shell does not support array variables!
    \# dash, bash, ksh and others do, however

## User input

    echo "Enter user name: "
    read -r FIRST_NAME
    echo "Current user name is $FIRST_NAME"

## Operators (arithmetic)

    VAL=$((2 + 2))

    \# +  (Addition) 
    \# -  (Subtraction) 
    \# *  (Multiplication)
    \# /  (Division) 
    \# %  (Modulus) 
    \# =  (Assignment) 
    \# == (Equality) 
    \# != (Not Equality)

## Operators (relational)

    [ "$VAL" -eq 4 ]
    \# -eq (equal)
    \# -ne (not equal)
    \# -gt (greater than)
    \# -lt (less than)
    \# -ge (greater or equal)
    \# -le (less or equal)

## Operators (boolean)

    \# && (AND)
    \# || (OR)
    \# !  (NOT)

## Operators (string)

    NAME="Tom"
    [ "$NAME" = "Tom" ]

    \# =   (equal)          
    \# !=  (not equal)
    \# -z  (zero length)    
    \# -n  (non-zero length)
    \# str (not empty)

## Conditional statements (if…elif…else)

    NAME="Tom"

    if [ "$NAME" = "Tom" ];
    then
        echo "me"
    elif [ "$NAME" = "Peter" ];
    then
        echo "my cousin"
    else
        echo "someone else"
    fi

## Conditional statements (case)

    NAME="Tom"

    case $NAME in
        "Tom")
            echo "me"
        ;;
        "Peter")
            echo "my cousin"
        ;;
        *)
            echo "someone else"
        ;;
    esac

## Loops

### For

    for NUMBER in 0 1 2 3 4 5 6 7 8 9
    do
        echo $NUMBER
    done

### While

    I=0
    while [ $I -lt 10 ]
    do
        echo $I
        I=$(($I + 1))
    done

### Until

    I=0
    until [ ! $I -lt 10 ]
    do
        echo $I
        I=$(($I + 1))
    done

### Break

    for VAR1 in 1 2 3
    do
        for VAR2 in 0 5
        do
            if [ $VAR1 -eq 2 ] && [ $VAR2 -eq 0 ]
            then
                break 2
            else
                echo "$VAR1 $VAR2"
            fi
        done
    done

### Continue

    NUMS="1 2 3 4 5 6 7"

    for NUM in $NUMS
    do
        Q=$(($NUM % 2))
        if [ $Q -eq 0 ]
        then
            echo "$NUM is an even number"
            continue
        fi
        echo "Found odd number: $NUM"
    done

## Command substitution

    echo "Date is $(date)"

## Functions

    Hello () {
        echo "Hello, $1"
        return 0  # Can only return 0-255. Other data should be written   
        to stdout
    }

    Hello "Tom"
    RETURN=$?

    echo "This command exited with code $RETURN"

## Sources
[**POSIX Shell Tutorial**](https://www.grymoire.com/Unix/Sh.html)
[**POSIX shell cheat sheet**](https://steinbaugh.com/posts/posix.html)
[**GitHub - dylanaraps/pure-sh-bible: 📖 A collection of pure POSIX sh alternatives to external…**](https://github.com/dylanaraps/pure-sh-bible)
[**Shell Scripting Tutorial**](https://www.tutorialspoint.com/unix/shell_scripting.htm)

---
*Hi! 👋 I’m Tom. I’m a software engineer, a technical writer and IT burnout coach. If you want to get in touch, check out [https://tomdeneire.github.io](https://tomdeneire.github.io/)*