hello world in sh


hello world in sh

When I write a sh-script, this is how I start:

#!/bin/sh
# usage: ./greeter Johannes

set -eux
set -o pipefail  # only works in bash

greet() {
    echo "Hello $1"
}

greet "$1"

(Don’t forget to make the script executable: chmod +x greeter)

This template is useful because it encourages good standards.

This post is here mainly so I can find the template whenever I want to write a quick script. But since you are already here, lets go through it, line by line.

What is in the template

Shebang

#!/bin/sh

It allows you to run the script directly (./greeter Johannes) instead of with an interpreter (sh greeter Johannes).

Usage hint

# usage: ./greeter Johannes

A small reminder on how to use the script (because I will certainly forget it).

defensive programming

set -eux

If there is an error the script should stop immediately.

What it does (as described in bash -c "help set"):

The last one is great for debugging. If you want to read more about these flags with more context, start reading here.

set -o pipefail  # only works in bash

This is a bit of an outsider, because it is bash specific. I try to write my code as POSIX compliant as possible, but I don’t do so religiously. So this can stay in my opinion.

What it does is change the collective exit code of commands that are chained together by pipes.

Lets say you want to list all the home-directories sorted by alphabet. You would write ls /home | sort and get an exit code of 0: All is fine.

But what if you have a typo in it? ls /homee | sort will print ls: cannot access '/homee': No such file or directory to stderr, but the exit code still indicates that all is fine. That is because the exit code of the chain of commands is just the exit code of the last command - and sort did just fine with no input.

set -o pipefail will make this behave as expected: The first nonzero status code will determine the status code of the whole chain (and with the -e from above the script will abort). Only if every single command exits with 0 then whole command will have exit code 0 as well and the script will continue. In our case we would get an exit code of 2.

Function definition

greet() {
    echo "Hello $1"
}

Define a function in a POSIX compliant way. The arguments are not declared in the breakets as in python (that would be cool). Instead they are just assumed to be there and called with $1 (or $2 for the second argument, etc).

Function call and script arguments

greet "$1"

Call the above function with an argument. The argument could be any string (greet "Sandra"), but I chose to use to forward the first argument of the script.

Script done

Now you can just script away. By the way, make sure to check it for errors with the incredible shellcheck.