2f88af30cd090d41d4cf0ce1919267e9.ppt
- Количество слайдов: 53
CPS 393 Introduction to Unix and C START OF WEEK 4 (UNIX) 3/18/2018 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 PS 1 -primary prompt string PS 2 -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 ) 3/18/2018 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: – PS 1='${PWD}> ' 3/18/2018 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=kc 3500 • e. g. , myenv HOME PRINTER – should print a line such as: HOME=/home/dwoit 3/18/2018 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 3/18/2018 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 3/18/2018 Course material created by D. Woit 6
Quoting • 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 3/18/2018 Course material created by D. Woit 7
Single versus double quotes • 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" • quotes stop filename substitution: * (like in echo files are “*” ) • • • E. G lets us evaluate variables e. g. , echo "dir is ${PWD}" # dir is /home/jmisic/cps 393 echo 'dir is ${PWD}' # dir is ${PWD} e. g. , grep "${Starkkids[2]}” got. txt # looks for Arya for example grep '${PWD}' * # looks for ${PWD} 3/18/2018 Course material created by D. Woit 8
Role of backslash character • 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 PS 2, to see yours do either: • env | grep PS 2 or echo ${PS 2} 3/18/2018 Course material created by D. Woit 9
Meaning and use of backquotes • Shell treats string in backquotes (accent graves) as a command 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. 3/18/2018 Course material created by D. Woit 10
conditional test is heart of control structure • • 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 3/18/2018 Course material created by D. Woit 11
Test –conditional test, cont. • NAME=“Arya" • test $NAME = “Arya“ # put a space around = • echo $? – 0 • • test n 1 -eq n 2 ## $? true if number n 1 equal to n 2 • also -ne, -lt, -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 3/18/2018 Course material created by D. Woit 12
EXPR • 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 3/18/2018 Course material created by D. Woit 13
Expr cont. • 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 3/18/2018 Course material created by D. Woit 14
Arithmetic Evaluation • 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 3/18/2018 Course material created by D. Woit 15
Control Structures • ; 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 3/18/2018 Course material created by D. Woit 16
Control Structures cont. • 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 3/18/2018 Course material created by D. Woit 17
Control Structures cont. • • 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 • 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 f 1 and f 2 containing “Stark" • without the ( ) what happens? Only direwolves. txt goes to grep and got. txt is catt-ed to stdout 1 st • Note: don't need spaces around ( ) but do need spaces around { ; } and semi-colon 3/18/2018 Course material created by D. Woit 18
Control Structures cont. • && test for true and execute – cmd 1 && cmd 2 #-- execute cmd 2 if cmd 1 returns true (true=0) – test -r direwolves. txt && cat direwolves. txt • || test for false and execute – cmd 1 || cmd 2 #-execute cmd 2 if cmd 1 returns false (false=1) – E. g: test –e mydir || mkdir mydir • e. g. , cmd 1 || ( cmd 2; cmd 3 ) – is it the same as cmd 1 || cmd 2; cmd 3 ? ? 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) ) 3/18/2018 Course material created by D. Woit 19
Conditional construct - if • • • if test-conditions then cmd-list 1 elif test-conditions #optional then #optional cmd-list 2 #optional else #optional cmd-list 3 #optional fi test-conditions is evaluated. If it returns a 0 exit status the if-part is done, Otherwise the next part is done. 3/18/2018 Course material created by D. Woit 20
If cont. • • • e. g. , you can type lines below into command line if test -f fn 1 # or if [ -f fn 1 ] then cp fn 1 fn 2 #only done if fn 1 is a file fi E. g • if [ -f fn 1 -a -x fn 1 ] # -a means and • • • then echo fn 1 is an executable file else echo fn 1 is not executable and/or not a file fi 3/18/2018 Course material created by D. Woit 21
If cont. • 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 3/18/2018 Course material created by D. Woit 22
If cont. • • • 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 3/18/2018 Course material created by D. Woit 23
Example program ff string • • • #!/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 ff 1 • #what happens if $1 is contained on many different lines of f 1? 3/18/2018 Course material created by D. Woit 24
Test operators • • 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. file 1 -nt file 2 #true, if file 1 is newer than file 2. • As mentioned above, man bash gives what can be used in [[ ]], which is slightly more extensive than what can be used in [ ] 3/18/2018 Course material created by D. Woit 25
HMWK 1 • • 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 change the 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 arg 2 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). 3/18/2018 Course material created by D. Woit 26
HMWK 2 • 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 "" ) 3/18/2018 Course material created by D. Woit 27
HMWK 3 • 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 "userid is not logged in" and exit 1 • (b) print "userid has been idle at least 1 minute and exit 0 • (c) print "userid has been idle less than 1 minute and exit 0 3/18/2018 Course material created by D. Woit 28
HMWK 4 • 1. re-write your homework program called nw (from unix 3. 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. 3/18/2018 Course material created by D. Woit 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" • ; ; 3/18/2018 • • • 11) echo "November" ; ; 12) echo "December" ; ; *) echo "some other month" ; ; esac exit 0 Course material created by D. Woit 30
Case cont. • • • case ${user-date} in 01|January) <-- multiple matches echo "first month" ; ; 02|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]) 3/18/2018 Course material created by D. Woit 31
Case cont. • • • # 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 3/18/2018 Course material created by D. Woit 32
For • Example • for variable in value 1 value 2 value 3. . . valuen • do • . . . • done # loops n times, • # 1 st. pass: $variable has value 1 • # 2 nd. pass: $variable has value 2 etc. 3/18/2018 • • • #!/bin/bash #Source tryfor echo "not much" > f 1 cp f 1 f 2; cp f 1 f 3; cp f 1 f 4 for file in f 1 f 2 f 3 f 4 do chmod +x $file done ls -l f? rm -i f 1 f 2 f 3 f 4 exit 0 Course material created by D. Woit 33
For examples • • • • #!/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 cla 1 for i in $@ do echo $i done echo “all params are $@” exit 0 3/18/2018 • #!/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 Course material created by D. Woit 34
For examples • • • • #!/bin/bash #source rename. Pgm #renames all files whose name contains "sample" so that the #"sample" part of the name becomes "Ch 1. 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/Ch 1. sample/'` 2>/dev/null if [ $? = "0" ] # variable $? Contains status of prev. operation then echo copied $i else echo could not copy $i fi done 3/18/2018 Course material created by D. Woit 35
Hmwk 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 and a '*' 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. 3/18/2018 Course material created by D. Woit 36
Example scripts for, if etc • 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/cp 393/Unix 4/bak || mkdir /home/jmisic/cps 393/Unix 4/bak • for f in * # * means all files in current directory • do • if [ -f $f ] #or if test -f $f • then • cp ${f} /home/jmisic/cps 393/Unix 4/bak/${f} # works also without braces • fi • done • exit 0 3/18/2018 Course material created by D. Woit 37
Read command • 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 arg 1 arg 2 rest – #reads "words" on one line (strings separated by whitespace) – reads word 1 into arg 1, word 2 into arg 2, 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 "arg 1 arg 2" | (read x y; echo $x $y). – However, #$x and $y only have value INSIDE () • read -n 1 line # reads one character at a time ( so -nx reads x at a time) • Read utility is good for asking user for additional information 3/18/2018 Course material created by D. Woit 38
Example for use of read • In script below we remind user to enter arguments. • #!/bin/bash • • • #Source: backup 1 if [ $# -eq 0 ] # variable $# is number of arguments then echo "Enter filename" read fn else fn=$1 fi cp $fn ${fn}. bak exit 0 3/18/2018 Course material created by D. Woit 39
while • • while [. . . ] # test command do . . . done • Executes commands between do and done as long as exit status of test command is 0. • • #!/bin/bash #Source: list 10 #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 list 10 a 3/18/2018 Course material created by D. Woit 40
While cont. • 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 fn 1` #all lines of fn 1 containing blah put in var y • if [ "$y" ] test is true if blah found at least once in fn 1 – otherways $y is null "" and if-condition is false 3/18/2018 Course material created by D. Woit 41
Example with infinite loop • • #!/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 str 1 str 2 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 3/18/2018 Course material created by D. Woit 42
Example with infinite loop cont. • • • • 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 3/18/2018 Course material created by D. Woit 43
While examples cont. • • • #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 3/18/2018 Course material created by D. Woit 44
While examples cont. • #!/bin/bash • # Source: add: • # adds : to front of each line of several files & concatenates result into # big-file • for file in fn? #<-- fn 1, fn 2, fn 3 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 3/18/2018 Course material created by D. Woit 45
Other control constructs • man bash gives lots of other control constructs, e. g. , • for (( expr 1 ; expr 2 ; expr 3 )) ; do commands ; done – Expr 1 is evaluated first – Expr 2 is evaluated repeatedly until it evaluates to 0 – Each time expr 2 evaluates to non-zero value, commands are executed and expr 3 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; • 3/18/2018 done Course material created by D. Woit 46
HMWK 1. 2. • • • 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 3/18/2018 Course material created by D. Woit 47
HMWK cont • • • And if file dog contained Abcde klm n Then numit
HMWK cont. • 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 num 2 • Modify the program num 2 above so that it will take any number of files as command line args, and number them consecutively on stdout. Call this program num 3 . For example: • if file f 1 was: – abc def – gh ij – k • and file f 2 was: – – a b c deflsjk Ds fkl 3/18/2018 Course material created by D. Woit 49
HMWK cont. • Then num 3 f 1 f 2 • • would print 1. abc def 2. gh ij 3. k 4. a b c 5. deflsjk 6. ds 7. fkl 3/18/2018 Course material created by D. Woit 50
HMWK cont. • Write a program called biggest that takes any number of arguments. • For all the arguments that are files, it finds • the file with the most words in it, and prints a line such as: • File whatever has largest number of words (37) • • • assuming the file called "whatever" has 37 words, which is more (or the same) as any other files in the current directory. If no arguments were valid files, then the following line should be printed to stderr: biggest: no valid filenames were specified You may find the wc command useful, especially wc -w 3/18/2018 Course material created by D. Woit 51
HMWK cont. • Use arrays to write a shell program called revarg that will print out its command line args in reverse order. 3/18/2018 Course material created by D. Woit 52
HMWK cont. • Write a shell program that tells you how many windows a user has • • open. Note that each open window is assigned a unique port number, which you can see with the w command. e. g. , > w dwoit pts/0 141. 117. 18. 31 . . eharley pts/3 141. 117. 18. 31 . . dwoit pts/2 moon. scs. ryer . . • This shows dwoit has 2 windows open (pts/0 and pts/2) • • The user is given as a command line argument to your program ($1). B. Extend your solution above to work for any number of userids on the command line, e. g. , > num. Windows dwoit eharley dwoit: 2 eharley: 1 3/18/2018 Course material created by D. Woit 53