CIS 191: Linux and Unix Class 3 February 11 th, 2015.

58
CIS 191: Linux and Unix Class 3 February 11 th , 2015

Transcript of CIS 191: Linux and Unix Class 3 February 11 th, 2015.

CIS 191: Linux and Unix

Class 3February 11th, 2015

Aside: Vim or Emacs in your shell!

• Add one of the following to your .bashrc to have basic editor commands added to your shell session!!!– set –o vi– set –o emacs

Outline

Review of Last Week

Branching Constructs

Loop Constructs

More Shell Scripting Constructs

Shell Constructs in Brief

• | - Pipes• <, >, 2> - Redirections• $( ), ` ` - Command Substitution• ; , &&, || - Command Lists• & - Run in background

Variables

• var=str assigns the text str to the variable var• $var is replaced with the text stored in var• echo $var prints the text in var• Variables that have not been set are replaced with the

empty string– Kind of like the null value in Java– So, echo $notset will print a blank line

Filename Completion

• Recall Wildcards– * will match any string of text (except for hidden files)– ? will match any single character (again, except hidden files)

• Some new stuff– [chars] matches any character enclosed

• [a-z] matches the range of characters from a to z– {list} is expanded to a space-delimited term once for each item

in the list• Recall the scp command from homework 1• So, twenty-{one,two,three,four} is expanded to

– twenty-one twenty-two twenty-three twenty-four

Note on notation

• From this point forward, single line shell interactions will still be preceded by a $, as before.– Input to the shell and resulting output will be on consecutive

lines

• Longer pieces of shell scripting will be written in consolas, but not preceded by a $.– Output will be displayed separately

Expansions Save Keystrokes

• A simple way to list all filesfor i in *; do

echo $i is a filedone

• From now on, expect to see this * notation instead of $(ls).

• So, to copy all CIS191 lecture notes to their own directory, just do– $ mkdir CIS191 && cp cis191* CIS191

Outline

Review of Last Week

Branching Constructs

Loop Constructs

More Shell Scripting Constructs

The If statement

if commandthen

commandselif commandthen

commandselse

commandsfi

xkcd.com/17

An If and test example!

if [ $SHELL = /bin/bash ]then

echo ‘You are using bash’else

echo ‘Your shell is not /bin/bash’fi

We can inline these statements with ;

• Equivalently… (and this holds similarly for for loops and other like constructs)

$ if [ $SHELL = /bin/bash ]; then echo ‘You are using bash’; else echo ‘Your shell is not /bin/bash’; fi

• This is bad form when writing your scripts to save and distribute or execute later or submit for a homework assignment!

• But it can be useful when writing a one liner in the command line (and you are not intending to save it)

test

• A simple test binary which is often found with if.• Often, we’ll see test run via its alias, the [ ] operator

– This is usually a shell command, not a program… (fyi)

• Note that all the following commands can be run by typing [ my arguments ] or test my arguments– It’s really just a matter of style– I’d recommend using the square braces in an if statement for

syntactic sugar

A couple more test notes…

• You have to write the notation exactly as we showed it here!

• [-e file] IS NOT THE SAME as [ -e file ]– You must have the space separating the brackets and other text!

• Also, to reiterate, the brackets are just an alias for the test command. To test for file existence, you could also type– test –e file

If and Test example

hours=$(date +%H)if [ $hours –lt 12 ]; then

echo It is before noon.fi

Note the semicolons before then in this usage case

Test Conditions (Strings)

• [ $str1 = $str2 ] => success if str1 is equal to str2• [ $str1 != $str2 ] => success if str1 is not equal to str2• [ -z $str ] => success if the string empty (null)• [ -n $str ] => success if the string is nonempty (not null)• [ $str1 < $str2 ] => success if str1 is less than str2 (alpha)• [ $str2 > $str2 ] => success if str1 is greater than str2

Test Conditions (numbers)

• The following convert the strings m and n to numbers before doing tests on them

• [ $m –eq $n ] => success if m is equal to n• [ $m –ne $n ] => success if m is not equal to n• [ $m –lt $n ] => success if m is less than n• [ $m – le $n ] => success if m is less than or equal to n• [ $m –gt $n ] => success if m is greater than n• [ $m –ge $n ] => success if m is greater than or equal to n

Test Conditions (files)

• [ -e filename ] => success if filename names a file• [ -d dirname ] => success if dirname names a directory• [ -r filename ] => success if filename names a file for

which the current user has read permissions• [ -o filename ] => success if filename names a file which

the current user owns• There are other options as well

– Checking write/execute permissions, filetype, etc

• See test(1) man page for more details– man test

How do we define “true” and “false”?

• In bash, “true” is a success code• And “false” is an error code• A success code is always 0

– And anything else is an error…

Some standard exit codes

• 0 – normal (true)• 1 – catchall for any general error• 2 – wrong usage• 126 – file is not executable• 127 – file not found• 128 – program killed by ^C

An example of using error codes

• Good for reporting errors

if rm file; thenecho Removal worked.

elseecho Removal failed.

fi

If – diff edition

#!/bin/sh#Say $1 is the usernameif diff $1/homework reference-answer; then

response=‘Incorrect answer!’else

response=‘Correct answer!’fiecho $response >> $1/grade.txt

If: grep edition

• Our old friend grep returns success or failure too…

#!/bin/sh# Assume $1 is the usernameif grep ‘pants’ myfile.txt; then

echo ‘Your file contains pants!’else

echo ‘Clothe your file please.’fi

Outline

Review of Last Week

Branching Constructs

Loop Constructs

More Shell Scripting Constructs

For: A foreach construct

• Use for loops to repeat an iteration over a set of values• The general form is as follows:

for i in listdo

commands…done• i is set to each of the items in list, in turn• commands is a list of commands to execute

For: example

for i in one two red bluedo

echo $i fishdone

The results are

one fishtwo fishred fishblue fish

For – example

for i in 19 37 61 optimus; doecho $i: prime

done

Internal Field Separator (IFS)

• This is how the shell knows how to split a string of text into a list which can be iterated through

• Make sure not to change this globally– Why might this be a bad idea?

• Change IFS locally only– Good for iterating through a comma-separated line, or a line

separated by semicolons… (etc)– Save old value of IFS

• $ OLDIFS=$IFS• $ IFS=‘,’• <DO STUFF>• $ IFS=$OLDIFS

Useful: Debug Mode

• You can run any script with – $ bash –x script.sh

• to enter debug mode– This will show each command being run (after substitutions and

aliases, and in a loop iteration

If, For, and Test: Better Together!!

• What does this do?

for i in $(ls)do

if [ -d $i ]echo $i is a directory

fidone

If, For, and Test: Better Together!!

• What does this do?

for i in $(ls)do

if [ -d $i ]echo $i is a directory

fidone

It lists directories, but not other types of files (and adds some flavor text to boot)

While – Another way to Loop!

• The while loop repeats an action while a condition is true– Sound familiar?

while condition do

commandsdone

Until – do until a condition is satisfied

• The until loop repeats an action until a condition is satisfied

until conditiondo

commandsdone

Wait until a minute is finished

while [ $(date +%S) != 00 ]; dosleep 1

doneecho A new minute just started.

• or, equivalently

until [ $(date +%S) == 00 ]; dosleep 1

doneecho A new minute just started.

read – User input

• This command allows you to get user input for your scripts

• $ read x• hey there• $ echo $x

– hey there

• $ read x y• hey there• $ echo $x and $y

– hey and there

While + read

• You can use the read function in conjunction with a while loop for short hand (read returns a status code)– read returns success if it gets input, and gives an error code if it

receives an EOF (^D) on a blank line.

while read xdo

echo You input ${x}.done

So, to exit a while read loop…

• We have a couple of options• We can kill the program

– ^C, ^\

• We can give read a zero-length string– ^D (EOF) on an empty line– Why won’t just pressing enter work?

• We can break out of the loop programmatically on some input

break and continue

• Basically the exact same functionality as in standard curly brace languages (c, java)

• break– If this command is encountered, then the script will exit the

innermost loop

• continue– If this command is encountered, then the loop will stop

execution of the loop body and skip to the next iteration of the loop

In example

while read x; do if [ $x == 'quit' ]; then break elif [ $x == 'skip' ]; then continue fi echo You entered ${x}.done

Redirection and while read loops

• Consider the following

while read line; doecho $line

done < myfile.txt

Leveraging read’s break on newline

• Since read breaks on the newline, we can pipe the contents of any file we like into the while-read loop’s standard input– This provides a very convenient way to loop through the lines in

a file…

Outline

Review of Last Week

Branching Constructs

Loop Constructs

More Shell Scripting Constructs

Arithmetic in Bash

Arithmetic in Bash

• As we discussed, the shell primarily operates on strings• But if you’ve ever programmed anything ever, then you

know that sometimes arithmetic is necessary…• In bash, arithmetic is placed inside $(( )).• For example

– $ echo The UID after yours is $(($UID + 1))– $ echo Six times nine is $((6 * 9))

Arithmetic Example

• Suppose you wanted to count the subdirectories using bash arithmetic

count=0for i in *; do

if [ -d $i ]; thencount=$(($count + 1))

fidoneecho There are $count subdirectories.

Bash and floating point arithmetic

• Bash doesn’t do floating point arithmetic– Just does typical integer truncation if an expression would

evaluate to a decimal point

Curly Braces for Dereferencing variables

• $ foo=herp• $ echo ${foo} • herp

• Considered to be good practice in all cases– Didn’t go into this last class for clarity…

• Also useful to expand variables when we want to append text to them without any whitespace…

• $ echo ${foo}derp• herpderp

Bash arrays

• It’s possible to define arrays in bash, too!– Though they are more like maps or dictionaries than arrays

• $ myarr[1]=first• $ myarr[2]=second• $ myarr[me]=ohmy

Dereferencing arrays requires { }

• Unlike other variables, dereferencing an array requires the use of curly braces!

• $ echo ${myarr[1]}• first• $ echo ${myarr[1]}not${myarr[2]}• firstnotsecond• $ echo me${myarr[me]}• meohmy• $ echo $myarr[me]• ohmy[me] (what?? – remember to use curly braces!)

Arrays are not backwards compatible!

• It’s important to note that POSIX compliant scripts should not make use of the array notation!

• Older interpreters such as sh and dash do not support arrays or the array syntax

• In general, if you are using arrays, you should consider writing the script in another language…

• Including them for completion more than as advice

Script Arguments

• Your scripts can accept CLI arguments too!– $1 is the first parameter to a script– $2 is the second parameter to a script

• and so on and so on…– $0 is the name of the script (the filename)– $@ is the list of arguments (as a bash array)– $* is also the list of arguments (as a space delimited string)– $# is the number of arguments passed to the script

shift operator for arguments

• Calling shift in a bash script will pop the first argument off the argument list, making $1=$2, $2=$3, and so on

• Another way to iterate through all input arguments!while [ $1 ]; do

stuffshift

done

Shell Functions

• You can place code that needs to be repeated in a function (just like in other programming languages)– Shell functions can be though of like sub-scripts– If you define a function in the current shell environment, then

the shell will tab complete the function for you!

name (){

commands}

Shell Functions

• Can also be written in one line (like anything else in bash)– $ name() { commands; }

• Arguments to functions are retrieved the same way they are to scripts– So, $1 is the first argument, $# is the number of arguments…

What does this do?

$ :() {: | :&}; :

Kaboom!

• $ () {: | :&}; :• Well, “:” is a valid name in bash… so it’s basically just a

function name. Let’s try replacing it with “bomb”.• $ bomb() {bomb | bomb&}; bomb

• Does this make things any clearer?

Breakdown

• This statement defines a function, :, which runs itself in the background twice– Then we call that function

• This is the canonical bash fork bomb• Don’t run this on Eniac.

– They’ll know it was you.

• Don’t run it on your own computer either. You’ll need to restart it (or the virtual machine).