540 likes | 617 Views
CPS 393 Introduction to Unix and C. START OF WEEK 4 (UNIX). 9/13/2014. Course material created by D. Woit. 1. Environment Variables. -always available -shell provides values -e.g., HOME -full path name of users home dir PATH -command search path PS1 -primary prompt string
E N D
CPS 393Introduction to Unix and C START OF WEEK 4 (UNIX) 9/13/2014 Course material created by D. Woit Course material created by D. Woit 1
Environment Variables • -always available • -shell provides values • -e.g., HOME -full path name of users home dir • PATH -command search path • PS1 -primary prompt string • PS2 -secondary prompt string (happens if it is waiting for the rest of a cmd, but you hit enter) • PWD -current dir • PRINTER -what your default printer is • CC -default C compiler (usually set to gcc) • (can set in makefile: CC=gcc ) 9/13/2014 Course material created by D. Woit Course material created by D. Woit 2
Environment Variables cont. • env command lists all your env vars and what they're set to • check the output of env • We can change env variables interactively e.g: • PS1='${PWD}> ' 9/13/2014 Course material created by D. Woit Course material created by D. Woit 3
HMWK • 1. write a shell program called myenv which takes one argument. The argument should be the name of an environment variable,such as PATH HOME etc. • myenv should print out the value of the variable given as the argument. If no argument is given, or the argument • is invalid, your program could do unpredictable things! • e.g., myenv PRINTER • should print a line such as: PRINTER=kc3500 • e.g., myenv HOME PRINTER • should print a line such as: HOME=/home/dwoit 9/13/2014 Course material created by D. Woit Course material created by D. Woit 4
Local variables -need no declaration • just assign value like in this example: • myname=Jelena #no spaces around = or Unix thinks it is shell cmd • myname='Dr. Misic' #quote if spaces or special chars • to access: • echo "Professor is ${myname}" # {} optional but prevents ambiguities • to forget: • unset myname #as if it never existed • length operator # • myname=Jelena • echo ${#myname} #prints 6 (length of Jelena) • to forget: • unset myname #as if it never existed 9/13/2014 Course material created by D. Woit Course material created by D. Woit 5
Local variables • -Arrays: • Starkkids[0]=Robb • Starkkids[1]=Sansa • Starkkids[2]=Arya • echo ${Starkkids[1]} # Sansa • echo ${Starkkids[*]} # Robb Sansa Arya • echo ${#Starkkids[*]} #3 • or can set arrays in one step • Starkkids=(Robb Sansa Arya Bran Rickon) #here, Starkkids[0]=“Robb" • Typeset command below declares variable X as integer and gives it value: • typeset -i X=0 • echo ${Starkkids[X]} man bash says that typeset exists for compatibility with Korn shell and is deprecated in favor of declare 9/13/2014 Course material created by D. Woit Course material created by D. Woit 6
Quoting 9/13/2014 • We need to protect white-space characters in strings which we want to submit to command because: • shell scans cmd line & divides into words by white space • evaluates and substitutes for special chars • evaluates as cmd -options filelist • e.g., grep Jon Snow got.txt # is wrong • What happened here is that : • String Jon is looked up in files Snow and cast_got.txt • grep “Jon Snow” got.txt# is correct 9/13/2014 Course material created by D. Woit Course material created by D. Woit 7 7
Single versus double quotes 9/13/2014 • single quotes are most restrictive: • do not evaluate anything within • ignore metacharacters, special chars, whitespace, etc • double quotes: • as above, but evaluate $ (variable or command substitution), • ` (back-quote chars) and \ (backslash char) • can use to output a single quote: echo "That's all" • quotesstop filename substitution: * (like in echo files are “*” ) • E.G lets us evaluate variables • e.g., echo "dir is ${PWD}" # dir is /home/jmisic/cps393 • echo 'dir is ${PWD}' # dir is ${PWD} • e.g., grep "${Starkkids[2]}” got.txt # looks for Arya for example • grep '${PWD}'* # looks for ${PWD} 9/13/2014 Course material created by D. Woit Course material created by D. Woit 8 8
Role of backslash character 9/13/2014 as we saw before, backslash protects following char e.g., to print: $amount is what ?? echo \$amount is what \?\? backslash char \ also allows splitting of long cmd lines, for example: /home/jmisic> cat got.txt | grep \ >“Lannister" e.g., /home/dwoit> grep cat #looks in stdin for “cat" /home/dwoit> grep Ghost \ >direwolves.txt #looks in file direwolves.txt for “Ghost" note: ">" is my current secondary prompt PS2, to see yours do either: env | grep PS2 or echo ${PS2} 9/13/2014 Course material created by D. Woit Course material created by D. Woit 9 9
Meaning and use of backquotes 9/13/2014 • Shell treats string in backquotes (accent graves) as a command and evaluates it (in sub-shell) and substitutes cmd result in its place • e.g., • TODAY=`date` • echo $TODAY • prints: Sat Jan 18 17:12:06 EST 2014 • However, without the quotes string is not evaluated e.g.: • TODAY=date • echo $TODAY • prints: date • grep `pwd` * • Will print all lines which contain string which is output of pwd command. 9/13/2014 Course material created by D. Woit Course material created by D. Woit 10 10
conditional test is heart of control structure 9/13/2014 • check if file is: readable, writable, executable, a file, a dir • check if 2 strings or intigers are >, < or = • can do AND OR or NOT logic, etc. • shell variable $? is assigned with result of test: • 0 = true 1 = false (yes, backwards from C!) • e.g., test -x direwolves.txt • echo $? • 0 printed if file fname is executable; 1 otherways • Additional switches for test fname: • -r for readable; -w for writable • -f for regular file; -d for directory • -G if group of fname is same as users current group Course material created by D. Woit Course material created by D. Woit 11 11 9/13/2014
Test –conditional test, cont. 9/13/2014 • NAME=“Arya" • test $NAME = “Arya“ # put a space around = • echo $? • 0 • test n1 -eq n2 ## $? true if number n1 equal to n2 • also -ne, -lt, -gt, -ge, -o -a • e.g., test -x fname -a -d bin • test true (0) if fname is executable AND bin is a dir • - man test gives all the options 9/13/2014 Course material created by D. Woit Course material created by D. Woit 12 12
EXPR 9/13/2014 • evaluates arguments and *returns* true or false (1 or 0 like C!!) to stdout (not in $? ) • e.g., a=1 • b=2 • expr $a = $b # put a space around = • 0 • STR="MYNAME" • expr "$STR" = "MYNAME“ • 1 • Can return a numerical value e.g: • expr $a + $b • 3 9/13/2014 Course material created by D. Woit Course material created by D. Woit 13 13
Expr cont. 9/13/2014 • operators: *,/,%,+,-,=,!=,<,>,<=,>= • \_______/\_____________/ • int true/false • Following examples are equivalent (but no spaces between d and expr please) • d=`expr $a \* 5` or • d=`expr $a '*' 5` or • d=$(expr $a \* 5) • echo $d 9/13/2014 Course material created by D. Woit Course material created by D. Woit 14 14
Arithmetic Evaluation 9/13/2014 • bash can also do arithmetic without expr construct: • typeset -i x=1 • x=x+1 • echo $x • 2 # is printed on stdout • Notice the difference if you do: • y=1 • y=y+1 • echo $y • y+1 #is printed on stdout • $(( )) does arithmetic evaluation • e.g., • unset a ; b=5 • a=$(($b * 5)) ; echo $a # no spaces around = • 25 is printed on stdout 9/13/2014 Course material created by D. Woit Course material created by D. Woit 15 15
Control Structures 9/13/2014 • ; separates commands e.g.: typeset -i x=1; x=x+1; echo $x • () execute in sub-shell - has all variables from calling shell • any variables it sets are gone when done • anything that alters shell environment is gone when done • {} execute in current shell - has all variables from calling shell • any variables it sets are still set in calling shell when done • some things that alter shell environment are still set when done (man bash search subshell) • e.g., (but space after { please ) • /home/dwoit: x=4;y=2; ( x=9;y=9; echo $x $y; ); echo $x $y • 9 9 • 4 2 • /home/dwoit: x=4;y=2; { x=9;y=9; echo $x $y; }; echo $x $y • 9 9 • 9 9 9/13/2014 Course material created by D. Woit Course material created by D. Woit 16 16
Control Structures cont. 9/13/2014 • Note: if you put a shell program in {}, and that shell program changes the environment (sets a variable for example), it is NOT changed in calling shell of {} (because SHELL PGMS cannot change calling environment). • this is because separate process is created to execute script • E.g. if shell program xy contained statements : • x=9;y=9; echo $x $y; • then all these would give same output: "9 9 \n 4 2" • x=4;y=2; ./xy; echo $x $y • x=4;y=2; ( ./xy; ); echo $x $y • x=4;y=2; { ./xy; }; echo $x $y # please note a space in { ./xy 9/13/2014 Course material created by D. Woit Course material created by D. Woit 17 17
Control Structures cont. 9/13/2014 • To get a shell program to run in current environment, do • . ./shell.pgm # (which is dot space dot backslash shell.pgm) • e.g., • /home/dwoit: x=4;y=2; . ./xy; echo $x $y • 9 9 • 9 9 • both () and {} group stdout of multiple cmds into 1 stream • Eg. (cat got.txt; cat direwolves.txt) | grep -c Stark • remember -c counts matching lines and returns a number • prints num of lines in f1 and f2 containing “Stark" • without the ( ) what happens? Only direwolves.txt goes to grep and got.txt is catt-ed to stdout 1st • Note: don't need spaces around ( ) but do need spaces around { ; } and semi-colon Course material created by D. Woit Course material created by D. Woit 18 18 9/13/2014
Control Structures cont. 9/13/2014 • && test for true and execute • cmd1 && cmd2 #-- execute cmd2 if cmd1 returns true (true=0) • test -r direwolves.txt && cat direwolves.txt • || test for false and execute • cmd1 || cmd2 #-execute cmd2 if cmd1 returns false (false=1) • E.g: test –e mydir || mkdir mydir • e.g., cmd1 || ( cmd2; cmd3 ) • is it the same as cmd1 || cmd2; cmd3 ?? NO! • ! expr returns false if expr true; true if expr false • [ cmd ] evaluates cmd and returns status of 0 if cmd true, 1 if false it is a short form for test cmd (man test) • Note: [[ cmd ]] same but more functionality (for example, • it can do > < for strings, where as [ ] cannot (man bash) ) 9/13/2014 Course material created by D. Woit Course material created by D. Woit 19 19
Conditional construct - if 9/13/2014 • if test-conditions • then • cmd-list1 • elif test-conditions #optional • then #optional • cmd-list2 #optional • else #optional • cmd-list3 #optional • fi • test-conditions is evaluated. If it returns a 0 exit status • the if-part is done, Otherwise the next part is done. 9/13/2014 Course material created by D. Woit Course material created by D. Woit 20 20
If cont. 9/13/2014 e.g., you can type lines below into command line if test -f fn1 # or if [ -f fn1 ] then cp fn1 fn2 #only done if fn1 is a file fi E.g if [ -f fn1 -a -x fn1 ] # -a means and then echo fn1 is an executable file else echo fn1 is not executable and/or not a file fi 9/13/2014 Course material created by D. Woit Course material created by D. Woit 21 21
If cont. 9/13/2014 typeset -i a=0 if [ $a -eq 1 ] #both -eq and = OK then echo YES #not echoed fi #another example xvar=dog #a string if [ $xvar = "dog" ] then echo YES #echoed fi 9/13/2014 Course material created by D. Woit Course material created by D. Woit 22 22
If cont. 9/13/2014 • Note: -eq, -lt etc, are used for numbers and • = != for strings • str is true if str is not the null string “” • eg: • xvar=dog #a string • if [ $xvar ] • then • echo YES #echoed • fi • Eg. • If [ “” ]; then echo YES; else echo NULL; fi • Output NULL 9/13/2014 Course material created by D. Woit Course material created by D. Woit 23 23
Example program ff string 9/13/2014 #!/bin/bash #source ff if [ "`grep $1 direwolves.txt`" ] then echo string $1 is contained in file direwolves.txt else echo string $1 is not contained in file direwolves.txt fi After chmod +x ff, we execute ./ff Ghost #works because grep prints null to stdout if not found and #some string if it is found #what happens if run this with $1 not set? Remember fix it with “$1” like in ff1 #what happens if $1 is contained on many different lines of f1? 9/13/2014 Course material created by D. Woit Course material created by D. Woit 24 24
Test operators 9/13/2014 For test operators (things that can be used in test or [ ]) see man test Some interesting ones: -n string #true, if length of string is non-zero. -z string #true, if length of string is zero. -e file #true, if file exists. file1 -nt file2 #true, if file1 is newer than file2. As mentioned above, man bash gives what can be used in [[ ]], which is slightly more extensive than what can be used in [ ] 9/13/2014 Course material created by D. Woit Course material created by D. Woit 25 25
HMWK1 9/13/2014 • Write a shell program called sg that takes 2 command line arguments. • The first argument is a textual string; the second a file name. • If other than 2 args are supplied it prints: • sg: Usage: sg str file • (the sg is printed so that if you changethe name of the program, • the "Usage line" changes automatically.) • If the second arg is not a readable file, print: • sg: file xxx invalid or not readable • where "xxx" is arg2 • Your program will return 0 if string is contained somewhere in the • file, and 1 if something wrong with args, and 2 if string not in • file (but args OK). (use grep in your program). 9/13/2014 Course material created by D. Woit Course material created by D. Woit 26 26
HMWK 2 9/13/2014 • Re-write shell program ff from above slides so that it does something reasonable when the user invokes it without a command argument (or with a null argument as in: ff "" ) 9/13/2014 Course material created by D. Woit Course material created by D. Woit 27 27
HMWK 3 9/13/2014 Write a shell program that will tell you how long another user's session has been idle. If the user has more than one session, just look at the first one. To see idle time, use the "w" command or the who command with an option. The program will take a userid as an argument and will do one of (a), (b), or (c) below: (a) print "user userid is not logged in" and exit 1 (b) print "user userid has been idle at least 1 minute and exit 0 (c) print "user userid has been idle less than 1 minute and exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 28 28
HMWK 4 9/13/2014 • 1.re-write your homework program called nw (from unix3.txt) so that if no argument is passed, all of your entries in the current dir are printed (instead of only 10 as before). Change it so the argument is a simple integer, instead of -integer as before. • 2. write a shell program called x that makes your most recently created file executable. 9/13/2014 Course material created by D. Woit Course material created by D. Woit 29 29
case #!/bin/bash #Source: datecase mnth=`date +%m` # formats it as mm (month ) case ${mnth} in 01) echo "January" ;; 02) echo "February" ;; 03) echo "March" ;; 11) echo "November" ;; 12) echo "December" ;; *) echo "some other month" ;; esac exit 0 9/13/2014 9/13/2014 Course material created by D. Woit Course material created by D. Woit 30 30
Case cont. 9/13/2014 case ${user-date} in 01|Jan|January) <-- multiple matches echo "first month" ;; 02|Feb|February) . . . esac Can use glob constructs (explains why default is *) If wanted to match 01 or anything starting with Jan: 01|Jan*) If wanted to match anything with exactly 3 chars: ???) Match exactly 3 digits: [0-9][0-9][0-9]) 9/13/2014 Course material created by D. Woit Course material created by D. Woit 31 31
Case cont. 9/13/2014 • # in example below two levels of are needed due to • # arithmetic evaluation • case $(($count < 100)) in # outcome is 1 if true • 1) echo $count is less than 100;; • 0) echo $count is more than 99;; • esac 9/13/2014 Course material created by D. Woit Course material created by D. Woit 32 32
for variable in value1 value2 value3 ... valuen do ... done # loops n times, # 1st. pass: $variable has value1 # 2nd. pass: $variable has value2 etc. Example #!/bin/bash #Source tryfor echo "not much" > f1 cp f1 f2; cp f1 f3; cp f1 f4 for file in f1 f2 f3 f4 do chmod +x $file done ls -l f? rm -i f1 f2 f3 f4 exit 0 For 9/13/2014 9/13/2014 Course material created by D. Woit Course material created by D. Woit 33 33
#!/bin/bash #source cla #program to print out all command line args one at a time for i do echo $i done exit 0 Note: for i in "$@" also loops over command line args, like in cla1 for i in $@ do echo $i done echo “all params are $@” exit 0 #!/bin/bash #Source filedir #tells if each item in current dir is file or dir for file in * do if [ -f $file ] # or if test -f $file then echo "$file is file" else if [ -d $file ] # or if test -d $file then echo " $file is dir. " fi fi done exit 0 For examples 9/13/2014 9/13/2014 Course material created by D. Woit Course material created by D. Woit 34 34
For examples 9/13/2014 #!/bin/bash #source renamePgm #renames all files whose name contains "sample" so that the #"sample" part of the name becomes "Ch1.sample" for i in *sample* do #in following line destination file name for copy is obtained by sed cp $i `echo $i | sed -e 's/sample/Ch1.sample/'` 2>/dev/null if [ $? = "0" ] # variable $? Contains status of prev. operation then echo copied $i else echo could not copy $i fi done 9/13/2014 Course material created by D. Woit Course material created by D. Woit 35 35
Hmwk 9/13/2014 1.write a shell pgm called lst which acts like ls -F, using a shell for loop (Note ls -F puts a '/' after dir names anda '*' after any files that are user executable and a '@' before any that are symbolic links. Look at 'man bash' or 'man test' to find the test for symbolic links) 2. write a shell program called num that prints the number of entries in the current directory. USE A LOOP and COUNTER. Use no pipes. • 3. modify your program nw from previous homework so that if the argument is a number larger than the number of entries IN the current directory, the following message is printed: there are only $num entries in this directory The new nw should use your program num from above to assign the number of files/dirs to a variable. 9/13/2014 Course material created by D. Woit Course material created by D. Woit 36 36
Example scripts for, if etc 9/13/2014 • How would you copy all files in the current dir into a backup directory called /home/userid/bak (where userid is replaced by your userid), • assuming that if bak exists, it is used; if not, it is created first? • #!/bin/bash • #Source: backup • test -d /home/jmisic/cp393/Unix4/bak || mkdir /home/jmisic/cps393/Unix4/bak • for f in * # * means all files in current directory • do • if [ -f $f ] #or if test -f $f • then • cp ${f} /home/jmisic/cps393/Unix4/bak/${f} # works also without braces • fi • done • exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 37 37
Read command 9/13/2014 • read line < fn • echo $line #prints line 1 of file fn • in general reads 1 line of stdin • #returns non zero status value (in $?) if EOF (end-of-file) • read arg1 arg2 rest • #reads "words" on one line (strings separated by whitespace) • reads word1 into arg1, word2 into arg2, and the rest of the line into rest. • #linux bug: won't work if stdin from a pipe (unless within a "while" statement. Or if () after |, as in echo "arg1 arg2" | (read x y; echo $x $y). • However, #$x and $y only have value INSIDE () • read -n1 line # reads one character at a time ( so -nx reads x at a time) • Read utility is good for asking user for additional information 9/13/2014 Course material created by D. Woit Course material created by D. Woit 38 38
Example for use of read 9/13/2014 In script below we remind user to enter arguments. #!/bin/bash #Source: backup1 if [ $# -eq 0 ] # variable $# is number of arguments then echo "Enter filename" read fn else fn=$1 fi cp $fn ${fn}.bak exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 39 39
while [ ... ]# test command do ... done Executes commands between do and done as long as exit status of test command is 0. #!/bin/bash #Source: list10 #Note: command seq 1 10 #does the same thing x=1 while [ $x -le 10 ] #or while test $x -le 10 do echo $x x=$((x+1)) done exit 0 #if we had used typeset -i x=1 then could have just done x=x+1 See list10a while 9/13/2014 9/13/2014 Course material created by D. Woit Course material created by D. Woit 40 40
While cont. 9/13/2014 • while [ 1 ] infinite-loop • Note: nothing special about the "1", any non-null string will result in infinite loop like ones below: • while [ 0 ] , while [ mouse ] , while [ "mouse" ] • However while [ "" ] and while [ ] are both false (null string) • Example: • y=`grep blah fn1` #all lines of fn1 containing blah put in var y • if [ "$y" ] test is true if blah found at least once in fn1 • otherways $y is null "" and if-condition is false 9/13/2014 Course material created by D. Woit Course material created by D. Woit 41 41
Example with infinite loop 9/13/2014 #!/bin/bash #Source: countod #read in a number of strings from user (until user enters END or end) # and output the total number of strings that are files & the total #number that are directories. #note: if the user enters more than one string on a line, # will get if [ -f str1 str2 etc ] bash syntax error typeset -i ordfile=0 typeset -i dirfile=0 while [ true ] do echo Enter a file name or END to quit read filenam 9/13/2014 Course material created by D. Woit Course material created by D. Woit 42 42
Example with infinite loop cont. 9/13/2014 if [ "$filenam" = "END" -o "$filenam" = "end" ] then break #breaks out of the while loop, like in C #fyi. continue statement also available fi if [ -f $filenam ] then ordfile=ordfile+1 elif [ -d $filenam ] then dirfile=dirfile+1 fi done echo -e "The number of ordinary files:\t $ordfile“ # -e enables \t “ echo -e "The number of directories:\t $dirfile" exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 43 43
While examples cont. 9/13/2014 • #Source: profgone • # does nothing until prof logs off • # should run this in the background with & • while [ "`who | grep jmisic`" ] #backquotes to evaluate • # outcome of previous statement false when null string i.e. when jmisic logs off • do • sleep 60 #1 minute • done • echo "she's finally gone" • exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 44 44
While examples cont. 9/13/2014 #!/bin/bash # Source: add: # adds : to front of each line of several files & concatenates result into # big-file for file in fn? #<-- fn1, fn2, fn3 etc do cat $file | \ # remember \ extends the command to multiline while read line #<-- reads line 1 of stdin into var line do echo ":$line" done | cat >> big-file #just done >> big-file works too done #need >> or last file will clobber exit 0 9/13/2014 Course material created by D. Woit Course material created by D. Woit 45 45
Other control constructs 9/13/2014 • man bash gives lots of other control constructs, e.g., • for (( expr1 ; expr2 ; expr3 )) ; do commands ; done • Expr1 is evaluated first • Expr2 is evaluated repeatedly until it evaluates to 0 • Each time expr2 evaluates to non-zero value, commands are executed and expr3 is evaluated • This is similar to C which we will study soon. • select name [ in word ] ; do list ; done • The list of words following in is expanded generating list of items. • The set of expanded words is printed on stderr each preceeded by a number. • Select fname in * • do • Echo you picked $fname \($REPLY\) • break; • done 9/13/2014 Course material created by D. Woit Course material created by D. Woit 46 46
HMWK 9/13/2014 • If the numbers from 1 to 4321 were written out, how many times would the digit '5' appear? Write a shell program to figure this out. • write a shell program called numit which reads lines from stdin and outputs the lines with line numbers. • e.g., if stdin was • this is a line • this is now another line • and here is line • Then numit would print • 1. this is a line • 2. this is now another line • 3. and here is line 9/13/2014 Course material created by D. Woit Course material created by D. Woit 47 47
HMWK cont 9/13/2014 • And if file dog contained • Abcde • klm • n • Then numit <dog would print • 1. Abcde • 2. • 3. klm • 4. n 9/13/2014 Course material created by D. Woit Course material created by D. Woit 48 48
HMWK cont. 9/13/2014 • write a program like numit above, except that IF a command line arg is given, it will check to see if the arg is a file, and if so, will output to stdout that file with line numbers as above. If it's not a file, or not readable, it will print an error message. Call this program num2 • Modify the program num2 above so that it will take any number of files as command line args, and number them consecutively on stdout. Call this program num3 . For example: • if file f1 was: • abc def • gh ij • k • and file f2 was: • a b c • deflsjk • Ds • fkl 9/13/2014 Course material created by D. Woit Course material created by D. Woit 49 49
HMWK cont. 9/13/2014 • Then num3 f1 f2 • would print • 1. abc def • 2. gh ij • 3. k • 4. a b c • 5. deflsjk • 6. ds • 7. fkl 9/13/2014 Course material created by D. Woit Course material created by D. Woit 50 50