Skip to content

Shell overview

Startup files

Linting / code style

  • for general shell linting, use shellcheck
  • for bash, use checkbashism
    • see bash.md for more details on bashism
  • Also: shfmt

Linting in Vim

null-ls uses shellcheck

Ignoring

Ignore a line:

# shellcheck disable=SC2086

Shellcheck

Shellcheck fixing support

Still no native automitic fixing but as a workaround:

shellcheck -f diff test.sh |git apply

For multiple files:

find . -type f -iname '*.sh' -printf '%P\0' | xargs -0 shellcheck -f diff | git apply

There's also an example to use parallel jobs.

beautysh

Github

Quoting variables

https://github.com/koalaman/shellcheck/wiki/SC2086

Use array to pass i.e. cmd-line options:

opts=(-v --debug)
leap "${opts[@]}"

AWK

Felder herausschneiden

awk -F'<td>' '{ print $7 }'

Parse File

while read line; do
  DATE=`echo $line|cut -d " " -f 6-7`
  FILE=`echo $line|cut -d " " -f 8-`
  echo "$DATE, $FILE"
done < $TMPFILE

Sonderzeichen eleminieren

sed -e "s/[^[:digit:][:alpha:][:space:].,]//g"

Write to file

  cat > /home/billy/test << EOF
  Hello World!
  This is my stupid text file.
  EOF

Variables

Default Werte

arch=${4:-x86_64}
mem=${5:-512}

Usage

Usage() {
  cat <<EOF
  Usage: ${0##*/} [ options ] output user-data [meta-data]
}

Parse commandline arguments

  • see /usr/share/doc/util-linux/examples or man getopt

Short opts

short_opts="hi:d:f:m:o:v"
long_opts="disk-format:,dsmode:,filesystem:,help,interfaces:,output:,verbose"
getopt_out=$(getopt --name "${0##*/}" \
       --options "${short_opts}" --long "${long_opts}" -- "$@") &&
       eval set -- "${getopt_out}" ||
       bad_Usage
while [ $# -ne 0 ]; do
       cur=${1}; next=${2};
       case "$cur" in
               -h|--help) Usage ; exit 0;;
               -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
               -d|--disk-format) diskformat=$next; shift;;
               -f|--filesystem) filesystem=$next; shift;;
               -m|--dsmode) dsmode=$next; shift;;
               -i|--interfaces) interfaces=$next; shift;;
               --) shift; break;;
       esac
       shift;
done
#
## check arguments here
## how many args do you expect?
[ $# -ge 2 ] || bad_Usage "must provide output, userdata"
[ $# -le 3 ] || bad_Usage "confused by additional args"
#
output=$1
userdata=$2
metadata=$3

Error handling

error() { echo "$@" 1>&2; }
errorp() { printf "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }

check for exit code

if $(echo 'hi'|grep -q h); then; echo true; fi
if $(echo 'hi'|grep -q o); then; echo true; fi

Add timestamps to output

If the -i or -s switch is passed, ts timestamps incrementally instead. In case of -i, every timestamp will be the time elapsed since the last timestamp. In case of -s, the time elapsed since start of the program is used.

unbuffer leap --yes  --force deploy donkey | ts -i