cs136l module 3.
bash scripts.
A script is used to automate the execution of tasks.
A bash shell script is just a plain text file that contains a sequence of bash shell commands.
.sh for shell scripts
Mere convention as Linux Operating System has no conception of file extensions.
#!/bin/bash
#File: bash.sh
# a script that prints the date, current user, and current directory.
date
whoami
pwd#! followed by the path on the first line is called the shebang ( hash-bang ), referring to the # as a hash, and ! as a bang, used to denote the location of the shell.
Namely for some systems we have:
#!/usr/bin/env bashThe next two lines that begin with # adds commands to a script. The last three lines are a sequence of bash commands.
Ways to execute bash commands.
Typing the full absolute/relative path to the script.
e.g.
This only works if the file
basic.shgives the current user execute perms.To check, use
chmod
e.g.
Gives all users execute permissions !
Executing scripts through the
bashcommand.No need for execute permissions !
Other than bash commands, bash scripts have the abillity to:
Use Shell Variables.
Use Command Line Arguments Provided to the script
Read input from the input stream.
Use Conditional Statements
loops
functions
Bash allows one to store information as STRINGS in variables in the same naming conventions as
C
e.g.
There must be no whitespace between variable names, the equal symbols, and the value assigned. If the value contains whitespace the value must be surrounded by quotes.
e.g.
This prevents ambiguity between command-line arguments in bash!
Get the value of Shell Variables, by prefixing the variable name with ${var_name}
Brackets not required, but to prevent ambiguities they are included.
e.g.
Note concatenation of characters to form larger strings are as easy as adding the characters directly.
To not substitute values, use single quotes.
e.g.
Global Shell Variables.
By convention, environment/global variables are declared in uppercase.
printenvallows one to list all currently defined environmental variables in the system.
The $PATH variable is a string that contains a concatenation of a list of directories (not ordinary files) separated by colons. Run the code below to see what $PATH is set to in our play area.
Unix, uses the
$PATHvariable to search for programs.When an user types in a command/program on the shell, the shell searches the directories listed in the
$PATHvariableIf the command used is not found in the path, it will report a
command not found error.
Common Global Shell Variables
${PWD}
present working directory ( equivalent to executing pwd )
${HOME}
your home directory ( equivalent to ~ )
${SHELL}
your default shell
${PRINTER}
your default printer
${HOSTNAME}
your machine's name
${PATH}
your default search path for commands and programs
Command Line Arguments
Two ways to supply input to script.
Args supplied to script when script is executed
Input made available on the input stream.
For the first method, all arguments are made accessible to the ran script through special variables. Namely
${0}
name of currently-running script
${1},${2},...
arguments 1,2,... of current script/function
${#}
number of arguments supplied to command/function ( not including script name )
${@}
all arguments supplied to current script/function as separate strings ( not including script names )
e.g.
Checks if the first argument is in a file or not.
Shell replaces $1 with value provided
The ^ and $, forces the pattern to be the exact string provided.
shiftcommandMove the command line arguments one position to the left, with the first one being discarded
This command is used in conjunction with bash loops to iterate through the command line arguments !
Reading From Standard Input Stream
We do this with the built-in
readcommand
e.g.
Same code as above, just takes input from the input stream now.
If the input is not supplied the variable will take the ${REPLY} variable as default.
Which is typically the empty string.
Alternative:
For more information do
read --help
Conditional Statements
testCommand to evalate conditions
Takes command line arguments delimited by whitespace
These args represent the conditions needed to be computed.
Does
1=2?
Failure to use appropriate whitespace in separating out the arguments to the test command is one of the most common mistakes made by those just starting out with bash scripting. It indeed feels archaic and can lead to a lot of frustrations.
Typically called with square brackets,
[, insteadtestand[]are equivalent commands
e.g.
this expression is equal to the above
The requirement for full closure of brackets was simply a design choice by the devs, it is not actually not needed ?
testproduces no output.Instead sets a special shell variable called
?Access by
$?By convention most Linux Programs exit with a status code and the status code is available in the
?variable.By Convention:
0 status code equal a successful compile
non-zero status code associated with error
You might be familiar with the C convention of returning 0 from the main function of a C program to indicate success. This is no coincidence. After all, C was invented to implement the Unix Operating System.
Thus the
testprogram will exit with status code0, if condition is true, and1if not.
Every Command will return a status code, and thus will overwrite the $ variable.
Common Operators
That can be used with
test
==, !=
string equality, inequality
-eq, -ne
integer equality, inequality
-gt, -ge
integer greater than, integer greater than or equal to
-lt -le
integer less than, integer less than or equal to
deprecated: -a -o
and, or
!
negation
-e
file exists
-d
file exists and is a directory
-f
file exists and is a regular file ( contains user data in some specific format)
-r -w -x
file exists and is readable/writable/executable
-z
check if the length of a string is zero
Note not just the presence of binary operators but also unary ones
e.g.
Checks to see if file exists.
Command Conditions
e.g.
compared to
&&and||short circuits !
To summarize: do not use the -a or -o operators in test conditions. Instead, use the shell's && and || operators
[[syntax for writing conditionsTypically was not recommended due to portability concerns, but if you are sure the syntax works in the shell, it can be extremely convenient
There exists other features like
Regular Expression Matching
Use of Wildcards
We will not use these syntax in course

Left is uncondensed version for if-statements in bash.
Notice the uses of
testfor the conditions ?
Right is condensed version for if-statements in bash.
thenkeyword is placed on the same line as the conditionuses a
;Necessary for Shell to determine if the conditions done ( think
&&and||which formed from long expressions ) !
The if statements can be further condensed by writing the condensed version all in one line
Used when true and false bodies of the conditionals are short
i.e. single commands

First If Statement
Determines how good a password is, depending on if the password is in the password bank.
egrep naturally prints to the output stream, we don't want that, thus it goes to
/dev/nullwhere it is disregarded
Functions in Shell Scripts
Honestly I see many similarities between
Candbash scripting, like the module mentioned they are probably very closely relatedespicially in terms of linux, etc...
We can also use the function prefix, when defining functions, but as we seen, it is not required.
Just like C, a bash function must be defined/declared before it is called.
Functions don't require parentheus to denote functions unlike other programming languages with Bash
Recall: $0 returns the name of the currently running script.
Recall: $# returns the number of arguments supplied to script.
exit command is new. The first argument represents the status code.

Loops
Bash Shell supports
whileandforloops

Left is non-condensed
Right is condensed
Notice the semi-colon once again for condensed forms?
Recall shell variables hold strings, thus line 6, shows how to treat the variable as an integer, using the
$((expression))syntax
Alternatively
$((x++)),let x=$x+1, orlet "x = $x + 1"( recall how double quotes allowed spacing ).If input was nothing, its likely the empty string.
thus when
$1was used it creates.[1 -le ], which thus results in the unary operator error that we see.
Hopefully the questions above convinced you to never trust that a user will do what is expected. It is a good idea to bullet-proof your scripts against unexpected inputs. The ability to predict such unexpected use is more of an art than science. Over time, you will build an intuition of what could go wrong.
Thus, observe:
Note that
=~is the regular expression match operator.The operator treats the right operand as an extended regular expressions.
Returns 0 if matches the regex and 1 otherwise.
The =~ operator is only available using the [[]] syntax
Notice that we had separate error codes for different types of errors !
Bash For Loops

Sequence can be a list of ANYTHING
list of numbers, files, strings
Strings can be used as a sequence ( elements are delimited by space )
Notice AGAIN the
;used for the condensed version on the right?
or
.cc and .cpp are common extensions for C++ files.
Recall we can use mv ( move ) command to rename files
e.g.
the
%operator can be used to chop off a suffix from a string ( if its actually there ofc )
Thus,
Recall the globbing patterns are intercepted by the shell and replaced by all arguments that match such pattern?
Note the limitations of egrep , it returns every line that matches the pattern given, thus if trying to count how many occurrences of a word there are, it is useless for multiple occurrences in one line.
All # 's after the first one after simply comments in Bash Shell, its not needed.
e.g.
Notice the embedded command
cat?Shell intercepts it, executing and replacing for the desired result.
This becomes a sequence for the for-loop to use !
This
catcommand is necessary to avoid treating the second command line argument as a string but actually reads the contents !
Iterating over command line arguments
Note that this script relies on the fact that no arguments will indicate an empty string !
Think of the assumptions made in code!

Recall that ${@} is a reserved shell variable that contains all the arguments provided to the script delimited by whitespace.

Note

Using
$res = ..., will basically make it an equality expression (0 = ...), only use$when we need to output it !

ITS THE SAME PROBLEM AGAIN, $ IS USED WHEN YOU WANT TO OUTPUT THE CONTENTS OF THE VARIABLES, $ IS USED WHEN YOU WANT TO OUTPUT THE CONTENTS OF THE VARIABLE, OR ELSE ITS GONNA BE A STATIC name i.e. [ -d name]
As we said in our introduction, automating things that need to be done frequently can increase productivity. Writing scripts is one way to reduce the need to remember and manually redo the same tedious tasks. The question of which scripting language is the best is as controversial as the more hotly debated question "Which editor is the best?" (Editor war). Our intent with this lesson was to give you a crash course on writing shell scripts in Bash. You will certainly encounter them in the tech world and therefore it is a good idea to have at least a working knowledge.
Last updated