ICS 54 Klefstad Writing Shell Scripts Introduction . csh is a programming language . a shell script is similar to a C procedure or function . simple scripts can save you repeating frequent commands . others can be parameterized to perform complex functions . shell scripts are more portable than compiled C . csh programs often can be written in C, but it is easier to write in csh . many locally written shell scripts can be found in /usr/local . eg lock_acc offtrip ontrip rn rxterm tgrind rcslist mkrcs Invoking Shell Scripts . two ways to interpret a script, direct and indirect . in either case, a new shell is invoked to interpret the script . `direct interpretation` % csh file [ arg ...] - csh interprets the commands % sh file [arg ...] - sh interprets the commands . `indirect interpretation` . change mode of script text-file to be readable and executable chmod a+rx my_script . invoke like any other Unix command A Simple Example . a shell script, called `wf`, to see if any of your friends are logged on # This script lists users whose name matches an egrep # pattern contained in the file ~/.friends # For example, to show anyone whose last name # either smith or jones the file would contain # the pattern *smith|*jones who | egrep \"\`cat ~/.friends\`\" Who Interprets a Script . by default, sh is invoked to interpret the script . csh in invoked only if first character is a # (csh comment) . you may force a specific command to interpret your script with #! . eg #! /bin/csh -f . eg #! /bin/cat Script Parameters . `argv` contains the list of argument words . $#argv is the number of arguments in argv . $argv[i] is the value of the ith argument . i is short for argv[i] . shift variable . shifts elements of variable to the left, discarding the first . shift . shifts argv . glob wordslist . like echo, but performs filename expansion on wordlist More on Variables . $var - gives the entire value of variable var . $var[index] - gives the ith word in the value of array var . $#var - gives the number of words in value of array var . $?var - true only if var is set . variable names can be delineated by curly braces, {var} . history-like modifiers can be applied to variables h - head t - tail r - root e - extension q - enquote x - quote individual words gh, gr, gt, ge - apply globally to all elements of an array . eg set full_names = (src/foo.c bar.h baz.c zip) set root_names = (${full_name:gr}) . special variables . $0 - the shell script name (useful for error messages) . - the process number of csh Assignment Statement . % set . displays the value of all csh variables . % set var . sets var to the null value, same as zero for numeric variables . % set var = value . sets var to value, which is often a list of words in parentheses . spaces are necessary . % set var[N] = word . sets the Nth word of multiword value var to word . the Nth element must already exist . % unset pattern . removes variables whose name match pattern . @ is similar to set, but expressions can use C operators Expressions and Operators . all values are strings . may be used in while, if, and @ . strings of digits may represent numerical values . all C operators are available . eg + - / * % < > <= >= == != && || ! . also =~ !~ for comparing to patterns . other tests . -r file - true if file is readable by user . -w file - true if file is writable by user . -x file - true if file is executable by user . -e file - true if file exists . -o file - true if user owns file . -z file - true if file is empty . -f file - true if file is a plain file . -d file - true if file is a directory . { command } - true if command succeeds (with zero status) If-Then Statement . `if` (long form) similar to C if-then-else if (expr) then ... else if (expr2) then ... else ... endif . eg if (-e /usr/bin) then ls /usr/bin else echo No /usr/bin endif . `if` (short form), for simple commands with no else part if (expr) simple_command . eg if (-d f) ls f While Loop . `while` loops while an expression is true . syntax while (expression) ... end . eg @ i = 1 while ( i <= #path ) echo path[i] @ i ++ end Foreach Loop . `foreach` executes the body once for each value in wordlist . for the ith iteration, var has value of the ith word . syntax foreach var (wordlist) ... end . eg foreach f ($path) echo $f end Other Looping Constructs . continue . continue execution of the nearest enclosing loop . break . resumes execution after the end of the nearest enclosing loop . label: . must appear on a line by itself . labels the statement following the label . eg top: . goto label . control transfers to label . eg goto top . repeat N cmd . repeats the simple command cmd N times . eg repeat 1000 echo 'I will not chew gum in class\!' Switch Statement . multi-way branch based on the value of a string expression . case labels may contain normal file patterns . beware of missing "breaksw" - falls through to next case . syntax switch (string) case label: ... breaksw default: ... breaksw endsw . eg switch ($#argv) case 1: cat >> $1 breaksw case 2: cat < 1 >> 2 breaksw default: echo "Usage: $0 [ infile ] outfile" breaksw endsw Exit from a shell . exit will cause a shell script to terminate with a specified value . exit sets the variable `status`, default value is zero . syntax exit [ (expr) ] . `status` tells whether the last command succeeded of failed, e.g., do_something if ($status != 0) then echo "something failed" exit($status) endif Another Example . example using foreach, switch, if-then, and exit # collect script arguments according to name set cfiles flags others foreach f ($argv) switch ($f) case *.c: set cfiles = (f cfiles) breaksw case -*: set flags = (f flags) breaksw default: set others = (f others) breaksw endsw end if ($flags) then echo cfiles = cfiles \; flags = flags \; others = $others else echo You forgot to pass any options. ; exit(1) endif Input/Output . $< - reads a line from stdin . echo [ -n ] argument-list . prints the argument list followed by newline . -n suppresses newline . eg echo -n "Delete file: $f? " if (< =~ [Yy]*) /bin/rm -f f Shell Hooks . eval argument . evaluates the argument as a shell command, but in the current shell . eg echo -n $prompt set cmd = $< eval $cmd . exec command . executes the command in place of the current shell, which terminates . wait . causes csh to wait for all background jobs to finish . -h places them on the history list without executing them The Here Document . to redirect input from the shell script itself, i.e., from `here` . syntax command <