shell scripts 4 a shell usually interprets a single line of input, but we can also create a file...
Post on 22-Dec-2015
214 views
TRANSCRIPT
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 commentA 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
Exampleset 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 file case 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