# shell programming intro overview of the most useful features # what shell? the shell command language of the [portable operating system interface](http://pubs.opengroup.org/onlinepubs/9699919799) 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 a program 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 ... } ~~~ ## accessing arguments ~~~ name() { echo $@ } ~~~ ~~~ name() { echo $1 } ~~~ note the always empty parentheses ## 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 possibly 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 do not need to analyse the code to get an idea of what it is supposed to do * use long options like --option so that readers do not 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 if 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 ~~~