2018-07-02

shell programming intro

overview of the most useful features

what shell?

the shell command language of the portable operating system interface

short: posix shell, sh

bash/ksh/zsh are sh compatible shells

variables

definition

a=bc
a="bc d"

no space around =

substitution

a="echo test"
$a

-> echo test

"$a"

-> "echo test"

conditionals

conditions use the exit code of commands

if grep -Fq error development.log
then
  # code
elif test $? -eq 3
  # code
else
  # code
fi

"true" is an application that is usually installed

while true
do
  echo test
done

"for" automatically splits arguments after "in" at whitespace

for a in b c d e
do
  echo $a
done

one-liner

for a in *; do echo "$a"; done
while true; do echo test; done

special parameters

array of program arguments

$@

argument 1, 2, 3, ...

$1
$2
$3

last exit code

$?

number of program arguments

$#

command lists

; ignore exit code

&& continue if exit code is 0

|| continue if exit code is not 0

cd /tmp && echo test || echo xy ; echo z

left associative. evaluated like this

((cd /tmp && echo test) || echo xy) ; echo z

program output redirection

>> append to existing file

> truncate or create file then write

| pipe between standard output and standard input

< read from file

cat filename | tail >> output-file

sub-routines

name() {
  # code ...
}

note the empty parentheses

accessing arguments

name() {
  echo $@
}
name() {
  echo $1
}

usage

name 3 2 1

commands

operator argument ...

file as operator. executes a file

/usr/bin/echo test
./this_file
echo

the last one searches the file in directories listed in the environment variable $PATH

variable as operator

a=echo test
$a 3

sub-routine as operator

test() {
  tail > /tmp/output
}

cat filename | test
compress_javascript() {
  uglifyjs --compress --mangle $@
}

cat input.js | compress_javascript > output.js

$@ is used in this example to be able to eventually pass additional arguments to "uglifyjs"

subshells

evaluate shell code and get what would be written on standard output as a string

$()
$(code ...)
timestamp=$(date +%s)

example file

#!/bin/sh

# links config files to their destinations

install() {
  sources=$@
  cp --recursive --force --symbolic-link --verbose \
    --target-directory=/ $sources
}

if test $# -eq 0
then
  echo usage example: ./exe/install hostname
else
  install "$PWD/data/$1"/*
fi

explanations

#!/bin/sh is a so called hashbang that is used by the program execution system call to select a program to evaluate the file content with

# creates code comments that will be ignored until the end of the line

scripts should have a description at the top so that readers dont need to analyse the code to get an idea of what it is supposed to do

use long options like --option so that readers dont have to look up in man pages what single character flags like -s or combinations like -rsat stand for

the \ is used to escape a linebreak character and treat what follows on the next line as being on the current line

for statements like "if", put "then" on the following line, to not have to add an extra semicolon like "if; then"

"test" is a program that is usually installed that is also aliased as [

to execute a file

./filename
sh filename

tags: programming start q1 document guide computer bash tutorial posix shell