Transcription of Bash Tutorial - NTNU
1 bash TutorialEigil Obrestad and Erik Hjelm asAugust 18, 20152(OUSTERHOUT, J., Scripting: Higher-Level Programming for the 21st Century , IEEE Computer, Vol. 31, No. 3, March 1998, pp. 23-30.)From Ousterhout, 1998:While programming languages like C/C++ are designed for low-level construction of data struc-tures and algorithms, scripting languages are designed for high-level gluing of existing com-ponents. Components are created with low-level languages and glued together with !The following presentation is NOT meant to be a comprehensive/complete tour of the bash purpose is to get you started with some basic program constructions which you will recognize based the end of the presentation you will find pointers to more comprehensive need a GNU/Linux distribution ( Ubuntu) running on a physical or virtual machine with workingaccess to the internet, and in and open a terminal window, download the examples as we go along withwget http :// - bash /FILENAME(or download all at once with )You will find theFILENAMEon the second line of each example.
2 For each example do1. Downloadwget View the codecat FILENAME orless FILENAME3. Execute the codebash FILENAMEor (make it executable withchmod +x FILENAME)./FILENAMEIt is easy to write bash scripts, but sometimes your scripts will behave strangely. This is due to the fact thatthere are many pitfalls in bash . It is very easy to write statements that appear logical to you in your way ofthinking programming, but due to the nature of a shell environment such as bash , they will not produce theexpected results. I strongly recommend that you quickly browse (and remember as a reference) the followingexcellent document: use the following tool to check the quality of your script (you can also probably apt-get install shellcheck): World#!
3 / bin/ bash # "Hello world!"make executable and execute:chmod +x SheBang/HashBang#!is treated as a comment by the interpreter, but it has a special meaningto the operating system s program loader (the code that is run when one of theexecsystem callsare executed) on Unix/Linux systems. The program loader will make sure this script is interpretedby the program listed after the#!1 VARIABLES4 Since Unix/Linux does not use file endings for identifying the file, there is no reason for us to doso in scripts either. The OS knows from the SheBang/HashBang what interpreter to use. Howeverduring the development of a script it can be nice to know something about the file content basedon the file ending, so it is common to Since this Tutorial is about the Bashlanguage, including bash -specific features that are not POSIX-compliant, we stick VariablesSingle Variables#!
4 / bin/ bash # single "$firstname$lastname"echo "Hello$fullname , may I call you$firstname?"A single variable is not typed, it can be a number or a not put spaces before or after=when assigning values to you need to substitute a variable immediately before a string, the variablesumand the stringKB, use curly braces around the variable (you will have to do this every time for array elements aswell as you will see below):echo "disk usage is ${sum}KB"Scope: variables are global unless specified inside a block and starting with the keywordlocal.(in general, use lower case variable names, upper case implies it s a SHELL/ENVIRONMENT variable)Single and Double Quotes#!
5 / bin/ bash # Hello$nameecho "Hello$name"echo'Hello$name'Variables are expanded/interpolated inside double quotes, but not inside single quotes. We usedouble quotes when we have a ArraysArraysBash supports simple one-dimensional arrays#!/ bin/ bash # ('linux''windows')os[2]='mac'echo "${os[1]}"# print windowsecho "${os[@]}"# print array valuesecho "${!os[@]}"# print array indicesecho "${#os[@]}"# length of arrayAutomatic expansion of arrays (automatic declaration and garbage collection).os[2]='mac'canalso be written asos+=('mac')Associative Arrays#!/ bin/ bash # assoc -A user# must be declareduser=(\[frodeh ]="Frode Haug" \[ivarm]="Ivar Moe"\)user[lailas ]="Laila Skiaker"echo "${user[ivarm]}"# print Ivar Moeecho "${user[@]}"# print array valuesecho "${!}
6 User[@]}"# print array indices (keys)echo "${#user[@]}"# length of arrayAssociative arrays were introduced with bash version 4 in 2009. If we don t declare the variableas an associative array withdeclare -Abefore we use it, it will be an ordinary indexed [lailas]="Laila Skiaker"can also be written asuser+=([lailas]="Laila Skiaker") Structures/ClassesStructures/ClassesSorr y, no structs or classes in bash ..2 Command-line argsCommand-Line ArgumentsScriptname in $0, arguments in $1, $2, ..#!/ bin/ bash # cli "I am$0, and have$# arguments \first is$1" bash accepts the first nine arguments as$ $9, for further arguments use${10},${11}.
7 2 InputInput From User#!/ bin/ bash # input -n "Say something here:"read -r somethingecho "you said$something"Input From STDINSame way, commonly without an echo first#!/ bin/ bash # input -r somethingecho "you said$something"can be executed asecho "hey hey!" | ./input course, input from user is useread -rto avoidreadremoving backslashes in the System commandsInput from System CommandsYou can use $(cmd) (supports nesting) or `cmd` (deprecated)#!/ bin/ bash # input "$(uname -sr)"echo "I am running on$kernel in$(pwd)"This is also calledcommand substitution.`..`(backticks) is depreciated because it s difficult toread, and can create some problems, if/elseif/else#!
8 / bin/ bash # [[ "$#" -ne 1 ]]; thenecho "usage:$0 <argument >"fiNote: there must be spaces around [[ and ]] .There is also an older (slower) and more portable (meaning POSIX defined) operator, [ which isactually an alias for the operator test , meaning[ "$#" -ne 2 ]# is the same astest "$#" -ne OperatorsArithmetic ComparisonOperatorMeaning ltLess than gtGreater than leLess than or equal to geGreater than or equal to eqEqual to neNot equal to3 CONDITIONS8 String ComparisonOperatorMeaning<Less than, in ASCII alphabetical order>Greater than, in ASCII alphabetical order=Equal to==Equal to!=Not equal toFile TestsOperatorMeaning eExists sNot zero size fRegular file dDirectory lSymbolic link uSet-user-id (SetUID) flag setThere are many more file test operators of !]
9 Not&&And||OrNumerical or String Compare#!/ bin/ bash # if -num [[ "$#" -ne 2 ]]; thenecho "usage:$0 <argument > <argument >"exit 0elif [[ "$1" -eq "$2" ]]; thenecho "$1 is arithmetic equal to$2"elseecho "$1 and$2 arithmetic differs"fiif [[ "$1" == "$2" ]]; thenecho "$1 is string equal to$2"elseecho "$1 and$2 string differs"fiif [[ -f "$1" ]]; thenecho "$1 is also a file!"fi3 CONDITIONS9 This shows the if-elif-else construction, the difference between string and numerical comparison,and a file test the difference between eq and ==$ . 1 011 is arithmetic equal to 011 and 01 string differsBoolean example#!
10 / bin/ bash # if [[ 1 -eq 2 && 1 -eq 1 || 1 -eq 1 ]]; thenecho "And has precedence"elseecho "Or has precedence"fi# force OR precedence :if [[ 1 -eq 2 && (1 -eq 1 || 1 -eq 1) ]]; thenecho "And has precedence"elseecho "Or has precedence"fiAND is always (as known from mathematics courses) evaluated before OR (binds more tightly).Write it down in logic (truth table) if you are Switch/caseCase#!/ bin/ bash # -r anscase$ans inyes)echo "yes!";;&# keep testingno)echo "no?";;# do not keep testing*)echo "$ans ???";;esacSee also select and ITERATION104 ForFor loop#!/ bin/ bash # i in { }; doecho -n "$i "doneecho# something more useful:for i in /*; doif [[ -f$i ]]; thenecho "$i is a regular file"elseecho "$i is not a regular file"fidoneWe can also usefor i in $(ls -1 /)orfor i in $(stat -c "%n" /*)but this creates prob-lems if we have filenames with spaces, so it s much better to use bash builtin expansion operator*as we do in this example.