390 likes | 607 Views
Shell Scripts. A shell usually interprets a single line of input, but we can also create a file containing a number of lines of commands to be interpreted This file is a program known as a shell script The program can also contain control structures (if-then, loops)
E N D
Shell Scripts • A shell usually interprets a single line of input, but we can also create a file containing a number of lines of commands to be interpreted • This file is a program known as a shell script • The program can also contain control structures (if-then, loops) • Shell scripts allow a sequence of commands to be executed automatically (e.g. installation of a program - see /user_client/sybase/install)
CSH Input Processing • CSH transforms each command before it is executed by applying the following steps: • History substitutions • Alias substitutions • Variable substitutions • Command substitutions • File name expansions
Shell Script Invocation • A shell script may be invoked either explicitly: • csh file [arg…] or sh file [arg …] • Or implicitly by giving its name on the command line. • In this case, the file must be made executable (chmod +rx scriptfile) • The shell script is interpreted by a subshell spawned by the user’s interactive shell
A Simple Example #this script consults an on-line telephone database grep -i $1 $HOME/phonenumbers • To make this script executable, chmod +rx • Now it can be run from the command line A comment A positional parameter An environment variable
Shell Script Basics • A shell script consists of a sequence of built-in and nonbuilt-in commands separated by ; or NEWLINE • Comments begin with a # • Script execution is aborted if a built-in command fails, goes to next command if a nonbuilt-in command fails. • Remember - built-in commands (e.g. alias) are part of the shell, nonbuilt-in commands (e.g. ls) are separate executable programs.
Executable Text Files • When the shell executes a nonbuilt-in command (i.e. a file) it first determines what type of file the command is. • Executable binary files have a “magic number” (a few bytes of code) at the beginning. • If this magic number is not found, the file is an executable text file. • The first few characters of the file tell which shell should process the file - #/bin/csh or #/bin/sh
Positional Parameters • Parameters can be passed to the script from the command line. • Inside the script, these parameters may be referenced by using the positional parameters $0, $1, $2, etc. • $0 refers to the command name (the name of the shell script)
CSH Scripts • The CSH scripting language is based on the C language. • The positional parameters can alternatively be referred to as $argv[1], $argv[2], etc. • $argv[*] is a list of all of the arguments given. • $#argv is the number of arguments given. • $argv[0] is undefined. Why?
Control Flow in CSH Scripts • Rather than just executing a predetermined sequence of commands, a script can be made flexible by using the control flow constructs available: • foreach • if • switch • while • goto • break • continue
Control Flow in CSH Scripts • The foreach command is used to execute a list of commands for each component of a list of words: foreach var (wordlist) commandlist end • Each time through the loop the variable var is assigned a word from wordlist, and the command list is executed
The foreach Command #!/bin/csh foreach x ( * ) echo Changing mode for $x chmod +rx $x end • Consider changing mode only for .exe files.
The if Command • Logical branching is provided by the if command: if (expr ) simple-command if ( expr ) then commandlist1 [else commandlist2] endif
The if Command ##check and set parameters if ( $#argv > 2 || $#argv < 1 ) then echo usage: “$0 [ from-file ] to-file” exit(1); else if ( $#argv == 2 ) then set from = $argv[1] set to = $argv[2] else set to = $argv[1] endif endir
The switch Command • A multiway alternative is provided by the switch command: switch ( str ) case pattern1: commandlist1 breaksw case pattern2: commandlist2 breaksw … default: commandlist endsw
The switch Command #!/bin/csh ## append $1 to $2 or standard input to $1 switch ( $#argv ) case 1: cat >> $argv[1] breaksw case 2: cat >> $argv[2] < $argv[1] breaksw default: echo 'usage: append [ from ] to' endsw
The while Command • The while command executes commands until an expression evaluates to zero: while ( expr ) commandlist end • Example set i = $#argv while ($i) echo $argv[$i] @ i-- end
Numerical Computations • Notice the ‘@’ in front of the i-- this allows a variable to take on a numeric value (otherwise script variables are string-valued) @ var = expr @ var[n] = expr • Examples: @ x = $#argv/2 @ argv[$j] = $j + 4 @ x += 3 @ i++
Other Control Flow Constructs • The goto command (goto word) provides an unconditional branch to a label of the form word: • The break command provides a means to exit the nearest enclosing while or foreach loop. • The continue command is similar to the break but transfers control to the next iteration rather than breaking out of the loop.
Expressions • Expressions in csh are similar to those in C: • Logical operators are the same (!, ||, &&) • Relational operators are the same with the addition of =~ for string match and !~ for string mismatch • Binary arithmetic operators are the same • Bitwise logical operators are the same • Parentheses are used to affect the order of evaluation • Logical constants (0 for false, 1 for true) are the same
Expressions • CSH adds file queries to test the status of a file • -r file (Is readable by the user) • -x file (Is executable by the user) • -o file (Is owned by the user) • -f file (Is an ordinary file) • -w file (Is writable by the user) • -e file (Exists) • -z file (Is of zero size) • -d file (Is a directory) • We can test whether a command has succeeded in a logical expression by enclosing the command in braces ({ and }): if ({ command1 } && { command2 } || { command3 } then
Variables • There are four kinds of variables: 1. Positional parameters (e.g. $1 and $argv[2]) 2. Special variables such as noglob and nonomatch 3. Environment variables such as DISPLAY and TERM 4. User-defined variables • Variables are set using the set or @ command: set dir = $cwd set list = (a b c d) @ k = $j + 1 set y = “$list” A multivalued variable Value of k is a string Use doublequotes for a multivalued variable
Variables • To select a portion of a multivalued variable, use $var[ selector ]where selector is an integer index, a range (e.g. 2-4) or all of the values (*). • $#var or ${#var} gives the number of strings in a multivalued variable.
Variable Modifiers • The value of a variable can be modified before it is used in an expression or command by using a variable modifier at the end of a variable. :h removes a trailing pathname component :t removes all leading pathname components :r removes a file extension (e.g. .xxx) :e removes the root name, leaving the extension :gh, :gr, :gt, :ge globally modify all strings of a multivalued variable :q quotes the substituted words, preventing further substitution :x is like :q but breaks into words at whitespace
Variable Modifiers #!/bin/csh set files = * foreach file ( $files ) echo $file if ( $file:e == for ) then mv $file {$file:r}.f77 endif end
Special Substitutions • To examine whether a variable is set or not use $?var or ${?var}. The string 1 is substituted is var is set, 0 if it is not. if ( ! $?term ) then set term = ‘tset - -m dialup:vt100’ endif • The special variable $$ substitutes the process number of the shell executing the script.
Special Substitutions #!/bin/csh ## Reminder service using calendar and mail set tfile = /tmp/remind_$$ ## temporary file calendar > $tfile ## consult calendar file if ( ! -z $tfile ) then ## send msg if necessary cat $tfile | /usr/ucb/mail -s \ "Reminder-calendar" $USER endif rm -f $tfile
Input and Output • The command echo words is used to display zero or more words to the standard output. • To prevent a newline after the last word, use echo -n words. • To read user input, the metavariable $< is used. A line from the standard input is read and returned as the value of the metavariable $< without variable- or file-name substitution.
The Here Document • It is possible to include input that is normally entered interactively inside of a script. This type of input is known as a here document and has the following form: command <<word zero or more lines of input included here word
The Here Document ## script name: timestamp ## usage: timestamp file cat >> $1 <<here ******************** RECEIVED by $user on `hostname` `date` here
The findcmd Script #!/bin/csh ## this procedure finds where given command is on search path ## the pathname for the command ## is displayed as soon as it is found ## otherwise a message to the contrary is displayed ## This script simulates the UNIX command "which" set cmd = $1 foreach dir ( $path ) if ( -e $dir/$cmd ) then echo FOUND: $dir/$cmd exit(0) endif end echo $cmd not on $path
The append Script #!/bin/csh ## append $1 to $2 or standard input to $1 switch ( $#argv ) case 1: cat >> $argv[1] breaksw case 2: cat >> $argv[2] < $argv[1] breaksw default: echo 'usage: append [ from ] to' endsw
The clean Script ## csh script: clean ## helps to rm unwanted files from a directory if ($#argv != 1) then echo usage: $0 directory; exit(1) endif set dir = $1 if (! -d $dir || ! -w $dir ) then echo $dir not a writable directory echo usage: $0 directory; exit(1) endif chdir $dir set files = *
The clean Script foreach file ($files) if (! -f $file ) then continue ## treat only ordinary files endif echo " " ## gives a blank line /bin/ls -l $file while (1) ## infinite loop echo -n "***** Delete $file or not?? [y, n, m, t, ! or q]" : set c = $< ## obtain user input switch ( $c ) case y: ## yes -- remove file if (! -w $file) then echo $file write-protected else rm -f $file if (-e $file) then
The clean Script echo cannot delete $file else echo "***** $file deleted" endif endif break ## to handle next file case n: ## no, don't remove file echo "***** $file not deleted" break ## to handle next filecase m: ## display file with more more $file; continue ## back to while loop case t: ## show tail of file tail $file; continue case \!: ## shell escape echo command:
The clean Script eval $< ## in this command the var $file can be used continue case q: ## quit from clean exit(0) default: ## help for user echo "clean commands: followed by RETURN\ y yes delete file\ n no, don't delete file, skip to next file\ m display file with more first\ t display tail of file first\ \! shell escape\ q quit, exit from clean" endsw end ## of while end ## of foreach
The ccp Script #!/bin/csh ## csh script : ccp --- conditional copy ## usage: ccp from to [ file ... ] ## where: `from' the source directory ## `to' the destination directory ## [file ... ] an optional list of files to be copied, ## otherwise, all files in `from' will be processed if ($#argv < 2) then echo usage: ccp from to "[ file ... ]"; exit(1) else if (! -d $1 || ! -d $2) then echo usage: ccp from to "[ file ... ]"; exit(1) endif
The ccp Script set dir = `pwd`; chdir $2; set to = `pwd` chdir $dir; chdir $1; ## now in from-dir if ($#argv == 2) then set files = * else set files = ( $argv[3-] ) endif foreach file ($files) if ( -d $file ) continue ## skip directories if (! -e $to/$file) then echo $to/$file is a new file cp $file $to; continue endif # if file in $from is more recent then cp find $file -newer $to/$file -exec cp $file $to \; end
The total Script #!/bin/csh ## csh script: total ## --- compute total disk space in bytes for a directory hierarchy ## a recursive script if ( $#argv == 1 && -d $1) then set x = `/bin/ls -l -d $1` else echo usage : $0 directory; exit(1) endif set count = $x[4] ## initialize byte count
The total Script foreach file ( $1/* $1/.* ) if ( -f $file ) then set x = `/bin/ls -l $file` @ count = $count + $x[4] else if ( $file:t == "." || $file:t == ".." ) then continue else if ( -d $file ) then set y = `$0 $file` ## recursive call @ count = $count + $y else echo $file not included in the total >>! /tmp/total.file endif end echo $count