cs136l module 3.

bash scripts.

circle-info

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
circle-info

#! 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 bash

The 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.

  1. Typing the full absolute/relative path to the script.

e.g.

  • This only works if the file basic.sh gives the current user execute perms.

    • To check, use chmod

e.g.

  • Gives all users execute permissions !

  • Executing scripts through the bash command.

    • 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.

circle-exclamation

e.g.

  • This prevents ambiguity between command-line arguments in bash!

circle-info

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.

circle-info

To not substitute values, use single quotes.

e.g.

Global Shell Variables.

  • By convention, environment/global variables are declared in uppercase.

  • printenv allows one to list all currently defined environmental variables in the system.

circle-info

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 $PATH variable to search for programs.

    • When an user types in a command/program on the shell, the shell searches the directories listed in the $PATH variable

      • If the command used is not found in the path, it will report a command not found error.

Common Global Shell Variables

Variable
Meaning

${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.

  1. Args supplied to script when script is executed

  2. Input made available on the input stream.

  • For the first method, all arguments are made accessible to the ran script through special variables. Namely

Variable
Meaning

${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.

  • shift command

    • Move 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 read command

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

  • test

    • Command to evalate conditions

    • Takes command line arguments delimited by whitespace

      • These args represent the conditions needed to be computed.

  • Does 1 = 2?

triangle-exclamation
  • Typically called with square brackets, [, instead

    • test and [] 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 ?

  • test produces 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

circle-info

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 test program will exit with status code 0, if condition is true, and 1 if not.

circle-exclamation

Common Operators

  • That can be used with test

Operators
Meaning

==, !=

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 !

circle-info

To summarize: do not use the -a or -o operators in test conditions. Instead, use the shell's && and || operators

  • [[ syntax for writing conditions

    • Typically 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 test for the conditions ?

  • Right is condensed version for if-statements in bash.

    • then keyword is placed on the same line as the condition

    • uses 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/null where it is disregarded

Functions in Shell Scripts

  • Honestly I see many similarities between C and bash scripting , like the module mentioned they are probably very closely related

    • espicially in terms of linux, etc...

circle-info

We can also use the function prefix, when defining functions, but as we seen, it is not required.

circle-info

Just like C, a bash function must be defined/declared before it is called.

circle-info

Functions don't require parentheus to denote functions unlike other programming languages with Bash

circle-info

Recall: $0 returns the name of the currently running script.

circle-info

Recall: $# returns the number of arguments supplied to script.

circle-info

exit command is new. The first argument represents the status code.

Loops

  • Bash Shell supports while and for loops

  • 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, or let "x = $x + 1" ( recall how double quotes allowed spacing ).

  • If input was nothing, its likely the empty string.

    • thus when $1 was used it creates.

      • [1 -le ], which thus results in the unary operator error that we see.

circle-info

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.

circle-info

The =~ operator is only available using the [[]] syntax

circle-info

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

circle-info

.cc and .cpp are common extensions for C++ files.

circle-info

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,

circle-info

Recall the globbing patterns are intercepted by the shell and replaced by all arguments that match such pattern?

circle-info

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.

circle-info

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 cat command 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!

circle-info

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 !

triangle-exclamation

circle-exclamation

Last updated