shell basics (bash)

These are the notes to a short tutorial I gave to my working group as part of our groundwork group meetings. Some parts here require GNU Bash.

1 Outline

1.1 Outline

  • user-output: echo
  • pipes: |, xargs, - (often stdin)
  • text-processing: cat/tac, sed, grep, cut, head/tail
  • variables (foo=1; echo ${foo})
  • subshell: $(command)
  • loops (for; do; done) (while; do; done)
  • conditionals (if; then; fi)
  • scripts: shebang
  • return values: $?
  • script-arguments: $1, $#, $@ and getopt
  • command chaining: ;, &, && and ||
  • functions and function-arguments
  • math: $((1+2))
  • help: man and info

2 Notes

2.1 user-output

echo "foobar"
echo foobar
echo echo # second echo not executed but printed!

2.2 Pipes

  • basic way of passing info between programs
echo foobar | xargs echo
# same output as
echo foobar
echo foo > test.txt # pipe into file, replacing the content
echo bar >> test.txt # append to file
# warning: 
cat test.txt > test.txt # defined as generating an empty file!

2.3 text-processing

echo foobar | sed s/foo.*/foo/ | xargs echo
# same output as 
echo foo
echo foo | grep bar # empty
echo foobar | grep oba # foobar, oba higlighted

2.4 Variables

foo=1 # no spaces around the equal sign!
echo ${foo} # "$foo" == "1", "$foobar" == "", "${foo}bar" == "1bar"

2.5 Subshells

echo $(echo foobar)
# equivalent to
echo foobar | xargs echo

2.6 loops

for i in a b c; do 
    echo $i
done
# ; can replace a linebreak
for i in a b c; do echo $i; done
for i in {1..5}; do # 1 2 3 4 5
    echo $i
done
while true; do 
    break; 
done
# break: stop
# continue: start the loop again

2.7 Quoting

foo=1
echo "${foo}" # 1
echo '${foo}' # ${foo} <- literal string
for i in "a b c"; do # quoted: one argument
    echo ${i}; 
done 
# => a b c
for i in a b c; do # unquoted: whitespace is separator!
    echo ${i}; 
done 
# a
# b
# c

2.8 conditionals

# string equality
a="foo"
b="bar"
if [[ x"${a}" == x"${b}" ]] ; then
    echo a
else
    echo b
fi
# other tests
if test -z ""; then 
    echo empty
fi
if [ -z "" ]; then
    echo same check
fi
if [ ! -z "not empty" ]; then
    echo inverse check
fi
if test ! -z "not empty"; then
    echo inverse check with test
fi
if test 5 -ge 2; then
    echo 5 is greater or equal 2
fi

also check test 1 -eq 1, and info test.

2.9 scripts: shebang/hashbang

#!/usr/bin/env bash
echo "Hello World"
chmod +x hello.sh
./hello.sh

2.10 Scripts: return value

echo 1
echo $? # 0: success
grep 1 /dev/null # fails
echo $? # 1: failure
exit 0 # exit a script with success value (no further processing of the script)
exit 1 # exit with failure (anything but 0 is a failure)

2.11 define shell arguments with getopt

# info about this script
version="shell option parsing example 0.1"
# check for the kind of getopt
getopt -T > /dev/null
if [ $? -eq 4 ]; then
    # GNU enhanced getopt is available
    eval set -- `getopt --name $(basename $0) --long help,verbose,version,output: --options hvo: -- "$@"`
else
    # Original getopt is available
    eval set -- `getopt hvo: "$@"`
fi

# # actually parse the options
# PROGNAME=`basename $0`
# ARGS=`getopt --name "$PROGNAME" --long help,verbose,version,output: --options hvo: -- "$@"`
# if [ $? -ne 0 ]; then
#   exit 1
# fi
# eval set -- $ARGS

# default options
HELP=no
verbose=no
VERSION=no
OUTPUT=no

# check, if the default wisp exists and can be executed. If not, fall
# back to wisp.py (which might be in PATH).
if [ ! -x $WISP ]; then
    WISP="wisp.py"
fi

while [ $# -gt 0 ]; do
    case "$1" in
        -h | --help)        HELP=yes;;
        -o | --output)      OUTPUT="$2"; shift;;
        -v | --verbose)     VERBOSE=yes;;
        --version)          VERSION=yes;;
        --)              shift; break;;
    esac
    shift
done
# all other arguments stay in $@
<<using-options>>

2.12 act on options

# Provide help output

if [[ $HELP == "yes" ]]; then
    echo "$0 [-h] [-v] [-o FILE] [- | filename]
        Show commandline option parsing.

        -h | --help)        This help output.
        -o | --output)      Save the executed wisp code to this file.
        -v | --verbose)     Provide verbose output.
        --version)          Print the version string of this script.
"
    exit 0
fi

if [[ x"$VERSION" == x"yes" ]]; then
    echo "$version"
    exit 0 # script ends here
fi

if [[ ! x"$OUTPUT" == x"no" ]]; then
    echo writing to $OUTPUT
fi

# just output all other arguments
if [ $# -gt 0 ]; then
    echo $@
fi

2.13 default help output formatting

prog [OPTIONAL_FLAG] [OPTIONAL_ARGUMENT VALUE] REQUIRED_ARGUMENT...
# ... means that you can specify something multiple times
# short and long options
prog [-h | --help] [-v | --verbose] [--version] [-f FILE | --file FILE] 
# concatenated short options
hg help [-ec] [THEMA] # hg help -e -c == -ec

2.14 Common parameters for commands

prog --help # provide help output. Often also -h
prog --version # version of the program. Often also -v
prog --verbose # often to give more detailed information. Also --debug

By convention and the minimal GNU standards

2.15 Command chaining

echo 1 ; echo 2 ; echo 3 # sequential
echo 1 & echo 2 & echo 3 # backgrounding: possibly parallel

grep foo test.txt && echo foo is in test.txt # conditional: Only if grep is successful
grep foo test.txt || echo foo is not in test.txt # conditional: on failure

2.16 Math (bash-builtin)

echo $((1+2)) # 3
a=2
b=3
echo $((a*b)) # 6
echo $((a**$(echo 3))) # 8

2.17 help

man [command]
info [topic]
info [topic subtopic]
# emacs: C-h i

more convenient info:

function i()
{
    if [[ "$1" == "info" ]]; then
        info --usage -f info-stnd
    else
        # check for usage from fast info, if that fails check man and if that also fails, just get the regular info page.
        info --usage -f "$@" 2>/dev/null || man "$@" || info "$@"
    fi
}
Inhalt abgleichen
Willkommen im Weltenwald!
((λ()'Dr.ArneBab))



Beliebte Inhalte

sn.1w6.org news