From: <ÓÉ Microsoft Internet Explorer 5 ±£´æ> Subject: UNIX Shell Programming Date: Tue, 27 Sep 2005 05:20:48 +0800 MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_0000_01C5C323.38595F20"; type="text/html" X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1506 This is a multi-part message in MIME format. ------=_NextPart_000_0000_01C5C323.38595F20 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Location: http://research.imb.uq.edu.au/~ksteube/Bshell/ =EF=BB=BF
------=_NextPart_000_0000_01C5C323.38595F20 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://research.imb.uq.edu.au/~ksteube/Bshell/roadmap.gif R0lGODlhdADXAPcAAAQEBGQvBJpkL6+vr9ra2u/v7/r6+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///yH5BAEAAP8ALAAAAAB0ANcA QAj/AP8JHEiwoMGDCBMiBKCwocOHECMSBMBQokEAAgIEEJBxY0aMHEOKDGmxpMUBAyqaXFmSIsuX EQGgpKgSps2bOHMSJMCzp8+fQIMKHUq0qFGfOgumPMq0qdOnPGsOBFCgqtWrWLNqTUkRpdevYL/S pDlSZFKcWtOqXVsVo0aObz+WnWtV6tm7B2XOpKrVrce4AUDOFck2a0q8iPN2hPtX8GCOfNnKTAxT poHLmDNr3sy5s+fPmmlSlogStOnTqFOrHh1zsevAj0UCiNo17F4Aqi/bZZ23p1/GcB0/hkr0cOLZ xH/+fi18sM/aXHk7TE50OeDmc6Vrd2i9cWyS28Mr/wbs/bsA8egnvi7/Pb377sHNn3ePHr5c8/Tr r4+PP394+7D15592AGJX1oDbFSgfggTud197DOYXoEsR+gfSdY/tNqCGOVHkYIAQRjhThTZxSB90 XolW31jINWWiTgNQJ+OMTykUWVoUGrQUjTwKxaJetr0o0I2FFamWggKSOCSQRBqZFZLfOVmXkhJB GZuUA1CZUm6dkRViXkBS+Y9lXJZpZplCjjaWbVzhduabqFn4oYEj9ShTmmdR9JSVw0EFpHGUtcgj n4OJ2ZCgUYGVo3rk8feloToRmh2kec65IKVJSXogppFamiSnJXr6KKgvaToSqTiZahaqoTb6YGys tv/6F3uwxmqTqyDWauuuvA75lmN49voQALMCR+eqJAZb0KJ5FbvYseBZmGV+Ho56Ikq7MqsdtsJS ++dthiobIYrgjslijzyOFiO67LZ71rrtxkucstoqtKO8+FY3rJRP3onuj9+yKRaLkfJrMFbEAvfs pQg2eXBhCe8HLUdUOvzwk87+Kp9k4vIGHUVSRtzoxALwOxmpH4tcLMkhd5xsxhuxbCSgFVLU5aIq G3spikROqyWcZqqIKplAFw20yyYRbfTScCINUZA2My11bhbCLABNAtM0dWcM5ryweclhDbXTalpN Mrrcelud2fLZqRfZENHotcZgV/cn3DD9y7Z5e1FyGe/cMTNMqZ5O8UzR3tYOHd2wiOvaLUSAXy34 49w1/hjlMVleKOaMK0x34pwvq/mkods4+qalJxQ5yamb7nngn7Y+0emnyt7s65LHbvuYtCO7+1S9 R/u7r7izPjzwxU/+++rK78687rY/D3rr0js+fPWX/x+PkM7f4a399+BLB5v3snMvW/gH4Xpsvc4H T7GYL7Jvo6jWN5yqXdhvvuF/xNKavX9paxh2ROSzwZGvMjTL1gEdEsBuLXAhCUSfRQImNE49kCXk alPNqiS/41Cwgy05V7suOEER5utvlDmhCpmCF3it8IVCuYsLYUhDEgpkhjRUoQ0Hcq8c5qtjkQHh DRHlQ3bRy0nM6mERfySwrAlxSBfDihLttqYmhuVH24niVtj0o4wZzz9aNJn75rOhMBpJVcIroxnX kj/SdW2NR6LfY/oFQK7AsS5jPOMOIcekKKKRIwarWYoshrA8hqyAFRvYVf5YMiwpMCWGnNkepcNI JP8i0lZtLIuTItg1PDEyRWycJEy2hBqyjGxyhjuZltw0NS+lcSGiLNUAtoamJ1JrlrTM5Vjqg8tc +pIzHuvlL4eZGXUJk5jINEBiSpPMZl7GgwEbJCudWTRvZfA206RmMauWvJGIbWxTG5ccnTOUbypK a55RUibrxKM2jahi45wL2mJ5k3WK5F+XtBBQGMmuBv7nKPYMyYxSRkkiMoWfLhqYeAy6pzGWUywD slM8y0IAniVLb93sHqVGONHawe9vY8QUQ/c0k476TqQHVRTyJNY8UM3GcPNTX0tlF9D3aY+R4Ksp GY+H0+/pNKcmfWX7Mlo/5wXVpjwNqU+PutPrKfVdpkzN6VN5GlWfTvV6Vb3pVZeX1aQS9X9UlSn0 aLpVo4p1eqn76VLPWtTolTV6XXXqV/UXVi/OlHpvpWlcl5dX6u11qCwdq1/ZCla5BhatpeupVufq RqwSlq6GPaVgEuHKnLsmFXZlsaUEN8vZzhIkIAA7 ------=_NextPart_000_0000_01C5C323.38595F20 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://research.imb.uq.edu.au/~ksteube/Bshell/rocks.gif R0lGODlhEAIeAPcAAP///0RERExMTFRUVF1dXWVlZW1tbXV1dX5+foaGho6OjpaWlp+fn6enp7e3 t8DAwNDQ0NjY2OHh4enp6fHx8fn5+f/////////////////5+djQ0K+np5aOjo6Ghp+WltjIyHVt bdDAwH51dW1lZcCvr2VdXaeWlp+OjpaGhl1UVFRMTMivr0xERH5tba+WlnVlZZ+Ghm1dXY51dWVU VIZtbZ9+fpZ1dY5tbad+fkw8PJZ1bcCnn6+WjqeOhp+Gfo51bbeflunY0Mi3r8Cvp6eWjn5tZWVU TLenn5aGfq+flo5+daeOfp+GdZ+Wjn51bci3p6eWhp+Ofq+WfvHp4bevp6+nn5aOho6GfnVtZY5+ benh2KeflmVdVKeWfuHQt9jIr6+fhtjQwPHp2Onh0I6GdcC3n9jQt8jAp+nht/////Hx6f//+cjI wNDQyJaWjo6Ohvn56YaGftjYyOnp2HV1bcjIt7e3p8DAr2VlXfHx2NjYwI6OfuHhwEREPNDYyK+3 p46WhoaOfuHp4aevp5+nn4aOhnV+dWVtZf///////+nx8YaOjm11dXV+fmVtbUxUVDM8PG1+hnV+ hlRdZYaOll1lbY6Wn3V+jo6Wp////////+Hh6enp8fHx+fn5/9DQ2MDAyMjI0Kenr6+vt7e3wJ+f p46OloaGjpaWn35+hm1tdXV1fqent11dZZaWp4aGllRUXUxMVH5+jnV1hkRETG1tfmVldY6Op4aG nzw8RH5+llRUZUxMXTMzPDw8TJ+Wt2VddZ+Wr9jQ4bevwJaOn3VtflRMXenh8aefr21lda+fwExE VMCv0MC3yJ+Wp7enwOHQ6a+ft+nh6fHp8fnx+djQ2MjAyNDI0OHY4cC3wI6GjoZ+hnVtdX51fm1l bbent2VdZa+fr1RMVI5+jtC30ExETH5tfqeOp0Q8RGVUZY51hqeWn2VUXdjI0K+fp3VlbW1dZY5t fsCvt5+Oln5tdYZldX5dba+Wn7efp5Z+hqeOlp+Gjo5tdZ91fhsbGyH5BAEAAAAALAAAAAAQAh4A QAj/AAEIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIBNWGwYK27AKFxReGLZlCwgQ JRhIIKitwTt6HhQs8HaARIFQnwReuMaOnL8k/pLK62fPG7kG1+IILZIkSYweKWJU9UdCnatvztih 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 ------=_NextPart_000_0000_01C5C323.38595F20 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://research.imb.uq.edu.au/~ksteube/Bshell/leaves.gif R0lGODlhAAR8APcAAP///4SEhIyMjJSUlJycnKWlpa2trbW1tb29vcbGxs7OztbW1t7e3ufn5+/v 7/f39+/n587GxtbOzt7W1r21ta2lpbWtrca9vZyUlKWcnOfe1sa9tffv597WztbOxr21re/n3s7G vefezsa9rf/3597Wxu/nzt7Wve/v5/f37///987OxtbWzt7e1ufn3r29ta2tpbW1rcbGvZSUjJyc lKWlnIyMhPf35///797ezufn1u/v3tbWxr29rcbGtc7OvbW1pf//562tnPf33qWllO/v1t7exufn ztbWvc7Otb29pcbGrf//3vf31u/vzufnxt7evdbWtc7Orf//1vf3zu/vxufnvff/zu/3xufvvff/ 1u/3zufvxs7Wrd7nvff/3u/31ufvztbevc7WtcbOrd7nxr3Gpff/5+/33ufv1tbexs7WvcbOtbW9 pa21nO//zuf3xt7vvdbntd7nzr3Gre//1uf3ztbnvc7etd7vxufv3sbOvaWtnPf/79bezs7WxrW9 ra21pe//3uf31s7evcbWtd7vztbnxr3Ord7n1r3GtZyllOf33sbWvd7v1s7extbnzr3OtbXGrefv 5+/378bOxs7Wztbe1t7n3rW9taWtpa21rb3GvYyUjJSclJylnISMhM7eztbn1sbWxrXGtb3OvcbO ztbe3q21tZScnMbGzq2lrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAABHwA QAj/ANmwQQQIEB1JdBKySUinB8MeDpewSTLmRyEyitgoUhTJBx1FPXy8QECyAI0fR45s4VImTJ4y MNWo4eHHTwIDBHIaQLCggQMAQIMKHUq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWLNq3cq1q9evYMOK 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 15nXQzgCUt6bTcBIiDiwJ6blbebmmwgIADs= ------=_NextPart_000_0000_01C5C323.38595F20--UNIX Bourne Shell Scripting
Ken Steube
Institute = for=20 Molecular Bioscience
The University of Queensland
Australia=20These notes teach you how to write and run Bourne shell scripts = on any=20 UNIX computer.=20
What do you need to know to follow along? This was originally = written=20 as a second class in UNIX. The first class taught how to use the = basic=20 UNIX commands (like sed, grep and find) and this class teaches how = to=20 combine these tools to accomplish bigger tasks.=20
In addition to the material in this course you might be = interested in=20 the Korn shell (ksh) and the Bourne again shell (bash), both of = which are=20 excellent shells that enchance the original Bourne shell. These = alternate=20 shells are upwardly-compatible with the Bourne shell, meaning that = a=20 script written for sh can run in ksh or bash. However, there are=20 additional features in bash and ksh that are not available in the = Bourne=20 shell.=20
The focus of this guide is to get you to understand and run = some Bourne=20 shell scripts. On several pages there are example scripts for you = to run.=20 On most of these pages there is a link you can click on (with the = right=20 mouse button) and download the script to your computer and run it. =
You will learn several things:=20
- Ability to automate tasks, such as=20
- Software install procedures=20
- Backups=20
- Administration tasks=20
- Periodic operations on a database via cron=20
- Any repetetive operations on files
- Increase your general knowledge of UNIX=20
- Use of environment=20
- Use of UNIX utilities=20
- Use of features such as pipes and I/O redirection =
For example, I recently wrote a script to make a backup of one = of the=20 subdirectories where I was developing a project. I quickly wrote a = shell=20 script that uses /bin/tar to create an archive of the entire = subdirectory=20 and then copy it to one of our backup systems at my computer = center and=20 store it under a subdirectory named according to today's date.=20
As another example, I have some software that runs on UNIX that = I=20 distribute and people were having trouble unpacking the software = and=20 getting it running. I designed and wrote a shell script that = automated the=20 process of unpacking the software and configuring it. Now people = can get=20 and install the software without having to contact me for help, = which is=20 good for them and good for me, too!=20
For shell script experts one of the things to consider is = whether to=20 use the Bourne shell (or ksh or bash), the C shell, or a richer = scripting=20 language like perl or python. I like all these tools and am not = especially=20 biased toward any one of them. The best thing is to use the right = tool for=20 each job. If all you need to do is run some UNIX commands over and = over=20 again, use a Bourne or C shell script. If you need a script that = does a=20 lot of arithmetic or string manipulation, then you will be better = off with=20 perl or python. If you have a Bourne shell script that runs too = slowly=20 then you might want to rewrite it in perl or python because they = can be=20 much faster.=20
Historically, people have been biased toward the Bourne shell = over the=20 C shell because in the early days the C shell was buggy. These = problems=20 are fixed in many C shell implementations these days, especially = the=20 excellent 'T' C shell (tcsh), but many still prefer the Bourne = shell.=20
There are other good shells available. I don't mean to neglect = them but=20 rather to talk about the tools I am familiar with.=20
If you are interested also in learning about programming in the = C shell=20 I also have a comparison=20 between features of the C shell and Bourne shell.=20
Table of Contents:
=20
- Review of a few Basic UNIX Topics (Page = 1)=20
- Storing Frequently Used Commands in Files: Shell Scripts (Page = 6)=20
- More on Using UNIX Utilities (Page = 9)=20
- Performing Search and Replace in Several Files (Page=20 11)=20
- Using Command-line Arguments for Flexibility (Page=20 14)=20
- Using Functions (Page=20 30)=20
- Miscellaneous (Page=20 38)=20
- Trapping Signals (Page=20 43)=20
- Understanding Command Translation (Page=20 50)=20
- Writing Advanced Loops (Page=20 59)=20
- Creating Remote Shells (Page=20 67)=20
- More Miscellaneous (Page=20 73)=20
- Using Quotes (Page=20 75)
=
Section 1: Review of a few Basic UNIX = Topics=20
Shell scripting involves chaining several UNIX commands = together to=20 accomplish a task. For example, you might run the 'date' command = and then=20 use today's date as part of a file name. I'll show you how to do = this=20 below.=20
Some of the tools of the trade are variables, backquotes and = pipes.=20 First we'll study these topics and also quickly review a few other = UNIX=20 topics.=20
Variables=20
- Topics covered: storing strings in variables=20
- Utilities covered: echo, expr=20
- To try the commands below start up a Bourne shell: =
/bin/sh- A variable stores a string (try running these commands in a = Bourne=20 shell)
name=3D"John Doe" echo $name- The quotes are required in the example above because the = string=20 contains a special character (the space)=20
- A variable may store a number
num=3D137- The shell stores this as a string even though it appears to = be a=20 number=20
- A few UNIX utilities will convert this string into a number = to=20 perform arithmetic
expr $num + 3- Try defining num as '7m8' and try the expr command again=20
- What happens when num is not a valid number?=20
- Now you may exit the Bourne shell with
exit
Page 1
I/O = Redirection=20
- Topics covered: specifying the input or capturing the = output=20 of a command in a file=20
- Utilities covered: wc, sort=20
- The wc command counts the number of lines, words, and = characters in=20 a file
wc /etc/passwd wc -l /etc/passwd- You can save the output of wc (or any other command) with = output=20 redirection
wc /etc/passwd > wc.file- You can specify the input with input redirection
wc = < /etc/passwd- Many UNIX commands allow you to specify the input file by = name or by=20 input redirection
sort /etc/passwd sort < /etc/passwd- You can also append lines to the end of an existing file = with output=20 redirection
wc -l /etc/passwd >> wc.file
Page 2
Backquotes=20
- Topics covered: capturing output of a command in a = variable=20
- Utilities covered: date=20
- The backquote character looks like the single quote or = apostrophe,=20 but slants the other way=20
- It is used to capture the output of a UNIX utility=20
- A command in backquotes is executed and then replaced by the = output=20 of the command=20
- Execute these commands
date save_date=3D`date` echo The date is $save_date- Notice how echo prints the output of 'date', and gives the = time when=20 you defined the save_date variable=20
- Store the following in a file named backquotes.sh=20 and execute it (right click and save in a file)
#!/bin/sh # Illustrates using backquotes # Output of 'date' stored in a variable Today=3D"`date`" echo Today is $Today- Execute the script with
sh backquotes.sh- The example above shows you how you can write commands into = a file=20 and execute the file with a Bourne shell=20
- Backquotes are very useful, but be aware that they slow down = a=20 script if you use them hundreds of times=20
- You can save the output of any command with backquotes, but = be aware=20 that the results will be reformated into one line. Try this: =
LS=3D`ls -l` echo $LS
Page 3
Pipes=20
- Topics covered: using UNIX pipes=20
- Utilities covered: sort, cat, head=20
- Pipes are used for post-processing data=20
- One UNIX command prints results to the standard output = (usually the=20 screen), and another command reads that data and processes it =
sort /etc/passwd | head -5- Notice that this pipe can be simplified
cat /etc/passwd = | head -5- You could accomplish the same thing more efficiently with = either of=20 the two commands:
head -5 /etc/passwd head -5 < /etc/passwd- For example, this command displays all the files in the = current=20 directory sorted by file size
ls -al | sort -n -r +4- The command ls -al writes the file size in the fifth column, = which=20 is why we skip the first four columns using +4.=20
- The options -n and -r request a numeric sort (which is = different=20 than the normal alphabetic sort) in reverse order
Page 4
awk=20
- Topics covered: processing columnar data=20
- Utilities covered: awk=20
- The awk utility is used for processing columns of data=20
- A simple example shows how to extract column 5 (the file = size) from=20 the output of ls -l
ls -l | awk '{print $5}'- Cut and paste this line into a Bourne shell and you should = see a=20 column of file sizes, one per file in your current directory.=20
- A more complicated example shows how to sum the file sizes = and print=20 the result at the end of the awk run
ls -al | awk '{sum =3D = sum + $5} END {print sum}'- In this example you should see printed just one number, = which is the=20 sum of the file sizes in the current directory.
Page 5
=
Section 2: Storing Frequently Used = Commands in=20 Files: Shell Scripts
Shell Scripts =
- Topics covered: storing commands in a file and = executing the=20 file=20
- Utilities covered: date, cal, last (shows who has = logged in=20 recently)=20
- Store the following in a file named = simple.sh=20 and execute it
#!/bin/sh # Show some useful info at the start of the day date echo Good morning $USER cal last | head -6- Shows current date, calendar, and a six of previous logins=20
- Notice that the commands themselves are not displayed, only = the=20 results=20
- To display the commands verbatim as they run, execute = with
sh -v simple.sh- Another way to display the commands as they run is with -x =
sh -x simple.sh- What is the difference between -v and -x? Notice that with = -v you=20 see '$USER' but with -x you see your login name=20
- Run the command 'echo $USER' at your terminal prompt and see = that=20 the variable $USER stores your login name=20
- With -v or -x (or both) you can easily relate any error = message that=20 may appear to the command that generated it=20
- When an error occurs in a script, the script = continues=20 executing at the next command=20
- Verify this by changing 'cal' to 'caal' to cause an error, = and then=20 run the script again=20
- Run the 'caal' script with 'sh -v simple.sh' and with 'sh -x = simple.sh' and verify the error message comes from cal=20
- Other standard variable names include: $HOME, $PATH, = $PRINTER. Use=20 echo to examine the values of these variables
Page 6
Storing File = Names in=20 Variables
- Topics covered: variables store strings such as file = names,=20 more on creating and using variables=20
- Utilities covered: echo, ls, wc=20
- A variable is a name that stores a string=20
- It's often convenient to store a filename in a variable=20
- Store the following in a file named variables.sh=20 and execute it
#!/bin/sh # An example with variables filename=3D"/etc/passwd" echo "Check the permissions on $filename" ls -l $filename echo "Find out how many accounts there are on this system" wc -l $filename- Now if we change the value of $filename, the change is = automatically=20 propagated throughout the entire script
Page 7
Scripting = With sed=20
- Topics covered: global search and replace, input and = output=20 redirection=20
- Utilities covered: sed=20
- Here's how you can use sed to modify the contents of a = variable:
echo "Hello Jim" | sed -e 's/Hello/Bye/'- Copy the file nlanr.tx= t=20 to your home directory and notice how the word 'vBNS' appears in = it=20 several times=20
- Change 'vBNS' to 'NETWORK' with
sed -e = 's/vBNS/NETWORK/g' < nlanr.txt- You can save the modified text in a file with output = redirection
sed -e 's/vBNS/NETWORK/g' < nlanr.txt > nlanr.new- Sed can be used for many complex editing tasks, we have only = scratched the surface here
Page 8
=
Section 3: More on Using UNIX = Utilities=20
Performing = Arithmetic=20
- Topics covered: integer arithmetic, preceding '*' = with=20 backslash to avoid file name wildcard expansion=20
- Utilities covered: expr=20
- Arithmetic is done with expr
expr 5 + 7 expr 5 \* 7- Backslash required in front of '*' since it is a filename = wildcard=20 and would be translated by the shell into a list of file names=20
- You can save arithmetic result in a variable=20
- Store the following in a file named a= rith.sh=20 and execute it
#!/bin/sh # Perform some arithmetic x=3D24 y=3D4 Result=3D`expr $x \* $y` echo "$x times $y is $Result"
Page 9
Translating = Characters=20
- Topics covered: converting one character to another,=20 translating and saving string stored in a variable=20
- Utilities covered: tr=20
- Copy the file sdsc.txt<= /A>=20 to your home directory=20
- The utility tr translates characters
tr 'a' 'Z' < = sdsc.txt- This example shows how to translate the contents of a = variable and=20 display the result on the screen with tr=20
- Store the following in a file named tr1= .sh=20 and execute it
#!/bin/sh # Translate the contents of a variable Cat_name=3D"Piewacket" echo $Cat_name | tr 'a' 'i'- This example shows how to change the contents of a variable=20
- Store the following in a file named tr2= .sh=20 and execute it
#!/bin/sh # Illustrates how to change the contents of a variable with tr Cat_name=3D"Piewacket" echo "Cat_name is $Cat_name" Cat_name=3D`echo $Cat_name | tr 'a' 'i'` echo "Cat_name has changed to $Cat_name"- You can also specify ranges of characters.=20
- This example converts upper case to lower case
tr 'A-Z' = 'a-z' < file- Now you can change the value of the variable and your script = has=20 access to the new value
Page 10
=
Section 4: Performing Search and = Replace in=20 Several Files
Processing = Multiple Files=20
- Topics covered: executing a sequence of commands on = each of=20 several files with for loops=20
- Utilities covered: no new utilities=20
- Store the following in a file named l= oop1.sh=20 and execute it
#!/bin/sh # Execute ls and wc on each of several files # File names listed explicitly for filename in simple.sh variables.sh loop1.sh do echo "Variable filename is set to $filename..." ls -l $filename wc -l $filename done- This executes the three commands echo, ls and wc for each of = the=20 three file names=20
- You should see three lines of output for each file name=20
- filename is a variable, set by "for" statement and = referenced as=20 $filename=20
- Now we know how to execute a series of commands on each of = several=20 files
Page 11
Using File = Name Wildcards=20 in For Loops
- Topics covered: looping over files specified with = wildcards=20
- Utilities covered: no new utilities=20
- Store the following in a file named l= oop2.sh=20 and execute it
#!/bin/sh # Execute ls and wc on each of several files # File names listed using file name wildcards for filename in *.sh do echo "Variable filename is set to $filename..." ls -l $filename wc -l $filename done- You should see three lines of output for each file name = ending in=20 '.sh'=20
- The file name wildcard pattern *.sh gets replaced by the = list of=20 filenames that exist in the current directory=20
- For another example with filename wildcards try this command =
echo *.sh
Page 12
Search and = Replace in=20 Multiple Files
- Topics covered: combining for loops with utilities = for global=20 search and replace in several files=20
- Utilities covered: mv=20
- Sed performs global search and replace on a single file =
sed -e 's/application/APPLICATION/g' sdsc.txt > sdsc.txt.new- The original file sdsc.txt is unchanged=20
- How can we arrange to have the original file over-written by = the new=20 version?=20
- Store the following in a file named s-and-r.sh=20 and execute it
#!/bin/sh # Perform a global search and replace on each of several files # File names listed explicitly for text_file in sdsc.txt nlanr.txt do echo "Editing file $text_file" sed -e 's/application/APPLICATION/g' $text_file > temp mv -f temp $text_file done- First, sed saves new version in file 'temp'=20
- Then, use mv to overwrite original file with new version=20
Page 13
=
Section 5: Using Command-line = Arguments for=20 Flexibility
What's = Lacking in the=20 Scripts Above?
- Topics covered: looping over files specified with = wildcards=20
- Utilities covered: no new utilities=20
- File names are hard-coded inside the script=20
- What if you want to run the script but with different file = names?=20
- To execute for loops on different files, the user has to = know how to=20 edit the script=20
- Not simple enough for general use by the masses=20
- Wouldn't it be useful if we could easily specify different = file=20 names for each execution of a script?
Page 14
What are = Command-line=20 Arguments?
- Topics covered: specifying command-line arguments=20
- Utilities covered: no new utilities=20
- Command-line arguments follow the name of a command
ls = -l .cshrc /etc- The command above has three command-line arguments
-l = (an option that requests long directory listing) .cshrc (a file name) /etc (a directory name)- An example with file name wildcards:
wc *.sh- How many command-line arguments were given to wc? It depends = on how=20 many files in the current directory match the pattern *.sh=20
- Use 'echo *.sh' to see them=20
- Most UNIX commands take command-line arguments. Your scripts = may=20 also have arguments
Page 15
Accessing = Command-line=20 Arguments
- Topics covered: accessing command-line arguments=20
- Utilities covered: no new utilities=20
- Store the following in a file named a= rgs1.sh=20
#!/bin/sh # Illustrates using command-line arguments # Execute with # sh args1.sh On the Waterfront echo "First command-line argument is: $1" echo "Third argument is: $3" echo "Number of arguments is: $#" echo "The entire list of arguments is: $*"- Execute the script with
sh args1.sh -x On the = Waterfront- Words after the script name are command-line arguments=20
- Arguments are usually options like -l or file names =
Page 16
Looping Over = the=20 Command-line Arguments
- Topics covered: using command-line arguments in a for = loop=20
- Utilities covered: no new utilities=20
- Store the following in a file named a= rgs2.sh=20 and execute it
#!/bin/sh # Loop over the command-line arguments # Execute with # sh args2.sh simple.sh variables.sh for filename in "$@" do echo "Examining file $filename" wc -l $filename done- This script runs properly with any number of arguments, = including=20 zero=20
- The shorter form of the for statement shown below does = exactly the=20 same thing
for filename do ...- Don't use
for filename in $*- Fails if any arguments include spaces=20
- Also, don't forget the double quotes around $@ =
Page 17
If Blocks=20
- Topics covered: testing conditions, executing = commands=20 conditionally=20
- Utilities covered: test (used by if to evaluate = conditions)=20
- This will be covered on the whiteboard=20
- See Chapter 8 of the book
Page 18
The read = Command=20
- Topics covered: reading a line from the standard = input=20
- Utilities covered: no new utilities=20
- stdin is the keyboard unless input redirection used=20
- Read one line from stdin, store line in a variable
read = variable_name- Ask the user if he wants to exit the script=20
- Store the following in a file named re= ad.sh=20 and execute it
#!/bin/sh # Shows how to read a line from stdin echo "Would you like to exit this script now?" read answer if [ "$answer" =3D y ] then echo "Exiting..." exit 0 fi
Page 19
Command Exit = Status=20
- Topics covered: checking whether a command succeeds = or not=20
- Utilities covered: no new utilities=20
- Every command in UNIX should return an exit status=20
- Status is in range 0-255=20
- Only 0 means success=20
- Other statuses indicate various types of failures=20
- Status does not print on screen, but is available thru = variable $?=20
- Example shows how to examine exit status of a command=20
- Store the following in a file named exit-status.sh=20 and execute it
#!/bin/sh # Experiment with command exit status echo "The next command should fail and return a status greater than = zero" ls /nosuchdirectory echo "Status is $? from command: ls /nosuchdirectory" echo "The next command should succeed and return a status equal to zero" ls /tmp echo "Status is $? from command: ls /tmp"- Example shows if block using exit status to force exit on = failure=20
- Store the following in a file named exit-status-test.sh=20 and execute it
#!/bin/sh # Use an if block to determine if a command succeeded echo "This mkdir command fails unless you are root:" mkdir /no_way if [ "$?" -ne 0 ] then # Complain and quit echo "Could not create directory /no_way...quitting" exit 1 # Set script's exit status to 1 fi echo "Created directory /no_way"- Exit status is $status in C shell
Page 20
Regular = Expressions=20
- Topics covered: search patterns for editors, grep, = sed=20
- Utilities covered: no new utilities=20
- Zero or more characters: .*
grep 'provided.*access' = sdsc.txt sed -e 's/provided.*access/provided access/' sdsc.txt- Search for text at beginning of line
grep '^the' = sdsc.txt- Search for text at the end of line
grep 'of$' sdsc.txt- Asterisk means zero or more the the preceeding character =
a* zero or more a's aa* one or more a's aaa* two or more a's- Delete all spaces at the ends of lines
sed -e 's/ *$//' = sdsc.txt > sdsc.txt.new- Turn each line into a shell comment
sed -e 's/^/# /' = sdsc.txt
Page 21
Greed and = Eagerness=20
- Attributes of pattern matching=20
- Greed: a regular expression will match the largest possible = string=20
- Execute this command and see how big a string gets replaced = by an=20 underscore
echo 'Big robot' | sed -e 's/i.*o/_/'- Eagerness: a regular expression will find the first match if = several=20 are present in the line=20
- Execute this command and see whether 'big' or 'bag' is = matched by=20 the regular expression
echo 'big bag' | sed -e 's/b.g/___/'- Contrast with this command (notice the extra 'g')
echo = 'big bag' | sed -e 's/b.g/___/g'- Explain what happens in the next example
echo 'black = dog' | sed -e 's/a*/_/'- Hint: a* matches zero or more a's, and there are many places = where=20 zero a's appear=20
- Try the example above with the extra 'g'
echo 'black = dog' | sed -e 's/a*/_/g'
Page 22
Regular = Expressions=20 Versus Wildcards
- Topics covered: clarify double meaning of asterisk in = patterns=20
- Utilities covered: no new utilities=20
- Asterisk used in regular expressions for editors, grep, sed=20
- Different meaning in file name wildcards on command line and = in find=20 command and case statement (see below)
regexp wildcard = meaning .* * zero or more characters, any type . ? exactly one character, any type [aCg] [aCg] exactly one character, from list: aCg- Regexps can be anchored to beginning/ending of line with ^ = and $=20
- Wildcards automatically anchored to both extremes=20
- Can use wildcards un-anchored with asterisks
ls *bub*
Page 23
Getting = Clever With=20 Regular Expressions
- Topics covered: manipulating text matched by a = pattern=20
- Utilities covered: no new utilities=20
- Copy the file animal= s.txt=20 to your home directory=20
- Try this sed command, which changes the first line of = animals.txt
sed -e "s/big \(.*\) dog/small \1 cat/" animals.txt- Bracketing part of a pattern with \( and \) labels that part = as \1=20
- Bracketing additional parts of a pattern creates labels \2, = \3, ...=20
- This sed command reverses the order of two words describing = the=20 rabbit
sed -e "s/Flopsy is a big \(.*\) \(.*\) rabbit/A big = \2 \1 rabbit/" < animals.txt
Page 24
The case = Statement=20
- Topics covered: choosing which block of commands to = execute=20 based on value of a string=20
- Utilities covered: no new utilities=20
- The next example shows how to use a case statement to handle = several=20 contingencies=20
- The user is expected to type one of three words=20
- A different action is taken for each choice=20
- Store the following in a file named c= ase1.sh=20 and execute it
#!/bin/sh # An example with the case statement # Reads a command from the user and processes it echo "Enter your command (who, list, or cal)" read command case "$command" in who) echo "Running who..." who ;; list) echo "Running ls..." ls ;; cal) echo "Running cal..." cal ;; *) echo "Bad command, your choices are: who, list, or cal" ;; esac exit 0- The last case above is the default, which corresponds to an=20 unrecognized entry=20
- The next example uses the first command-line arg instead of = asking=20 the user to type a command=20
- Store the following in a file named c= ase2.sh=20 and execute it
#!/bin/sh # An example with the case statement # Reads a command from the user and processes it # Execute with one of # sh case2.sh who # sh case2.sh ls # sh case2.sh cal echo "Took command from the argument list: '$1'" case "$1" in who) echo "Running who..." who ;; list) echo "Running ls..." ls ;; cal) echo "Running cal..." cal ;; *) echo "Bad command, your choices are: who, list, or cal" ;; esac- The patterns in the case statement may use file name = wildcards=20
Page 25
The while = Statement=20
- Topics covered: executing a series of commands as = long as=20 some condition is true=20
- Utilities covered: no new utilities=20
- The example below loops over two statements as long as the = variable=20 i is less than or equal to ten=20
- Store the following in a file named = while1.sh=20 and execute it
#!/bin/sh # Illustrates implementing a counter with a while loop # Notice how we increment the counter with expr in backquotes i=3D"1" while [ $i -le 10 ] do echo "i is $i" i=3D`expr $i + 1` done
Page 26
Example With = a while Loop=20
- Topics covered: Using a while loop to read and = process a file=20
- Utilities covered: no new utilities=20
- Copy the file while2= .data=20 to your home directory=20
- The example below uses a while loop to read an entire file=20
- The while loop exits when the read command returns false = exit status=20 (end of file)=20
- Store the following in a file named = while2.sh=20 and execute it
#!/bin/sh # Illustrates use of a while loop to read a file cat while2.data | \ while read line do echo "Found line: $line" done- The entire while loop reads its stdin from the pipe=20
- Each read command reads another line from the file coming = from cat=20
- The entire while loop runs in a subshell because of the pipe =
- Variable values set inside while loop not available after = while loop=20
Page 27
Interpreting = Options With=20 getopts Command
- Topics covered: Understand how getopts command works=20
- Utilities covered: getopts=20
- getopts is a standard UNIX utility used for our class in = scripts=20 getopts1.sh and getopts2.sh=20
- Its purpose is to help process command-line options (such as = -h)=20 inside a script=20
- It handles stacked options (such as -la) and options with = arguments=20 (such as -P used as -Pprinter-name in lpr command)=20
- This example will help you understand how getopts interprets = options=20
- Store the following in a file named getopts1.sh=20 and execute it
#!/bin/sh # Execute with # # sh getopts1.sh -h -Pxerox file1 file2 # # and notice how the information on all the options is displayed # # The string 'P:h' says that the option -P is a complex option # requiring an argument, and that h is a simple option not requiring # an argument. # # Experiment with getopts command while getopts 'P:h' OPT_LETTER do echo "getopts has set variable OPT_LETTER to '$OPT_LETTER'" echo " OPTARG is '$OPTARG'" done used_up=3D`expr $OPTIND - 1` echo "Shifting away the first \$OPTIND-1 =3D $used_up command-line = arguments" shift $used_up echo "Remaining command-line arguments are '$*'"- Look over the script=20
- getopts looks for command-line options=20
- For each option found, it sets three variables: OPT_LETTER, = OPTARG,=20 OPTIND=20
- OPT_LETTER is the letter, such as 'h' for option -h=20
- OPTARG is the argument to the option, such as -Pjunky has = argument=20 'junky'=20
- OPTIND is a counter that determines how many of the = command-line=20 arguments were used up by getopts (see the shift command in the = script)=20
- Execute it several times with
sh getopts1.sh -h -Pjunky sh getopts1.sh -hPjunky sh getopts1.sh -h -Pjunky /etc /tmp- Notice how it interprets -h and gives you 'h' in variable = OPT_LETTER=20
- Now you can easily implement some operation when -h is used=20
- Notice how the second execution uses stacked options=20
- Notice how the third execution examines the rest of the = command-line=20 after the options (these are usually file or directory names)=20
Page 28
Example With = getopts=20
- Topics covered: interpreting options in a script=20
- Utilities covered: getopts=20
- The second example shows how to use if blocks to take action = for=20 each option=20
- Store the following in a file named getopts2.sh=20 and execute it
#!/bin/sh # # Usage: # # getopts2.sh [-P string] [-h] [file1 file2 ...] # # Example runs: # # getopts2.sh -h -Pxerox file1 file2 # getopts2.sh -hPxerox file1 file2 # # Will print out the options and file names given # # Initialize our variables so we don't inherit values # from the environment opt_P=3D'' opt_h=3D'' # Parse the command-line options while getopts 'P:h' option do case "$option" in "P") opt_P=3D"$OPTARG" ;; "h") opt_h=3D"1" ;; ?) echo "getopts2.sh: Bad option specified...quitting" exit 1 ;; esac done shift `expr $OPTIND - 1` if [ "$opt_P" !=3D "" ] then echo "Option P used with argument '$opt_P'" fi if [ "$opt_h" !=3D "" ] then echo "Option h used" fi if [ "$*" !=3D "" ] then echo "Remaining command-line:" for arg in "$@" do echo " $arg" done fi- Execute it several times with
sh getopts2.sh -h -Pjunky sh getopts2.sh -hPjunky sh getopts2.sh -h -Pjunky /etc /tmp- Can also implement actions inside case statement if desired=20
Page 29
=
Section 6: Using Functions =
Functions=20
- Sequence of statements that can be called anywhere in script =
- Used for=20
- Good organization=20
- Create re-usable sequences of commands =
Page 30
Define a = Function=20
- Define a function
echo_it () { echo "In function echo_it" }- Use it like any other command
echo_it- Put these four lines in a script and execute it =
Page 31
Function = Arguments=20
- Functions can have command-line arguments
echo_it () { echo "Argument 1 is $1" echo "Argument 2 is $2" } echo_it arg1 arg2- When you execute the script above, you should see =
Argument 1 is arg1 Argument 2 is arg2- Create a script 'difference.sh' with the following lines: =
#!/bin/sh echo_it () { echo Function argument 1 is $1 } echo Script argument 1 is $1 echo_it Barney- Execute this script using
sh difference.sh Fred- Notice that '$1' is echoed twice with different values=20
- The function has separate command-line arguments from the = script's=20
Page 32
Example With = Functions=20
- Use functions to organize script
read_inputs () { ... } compute_results () { ... } print_results () { ... }- Main program very readable
read_inputs compute_results print_results
Page 33
Functions in = Pipes=20
- Can use a function in a pipe
ls_sorter () { sort -n +4 } ls -al | ls_sorter- Function in pipe executed in new shell=20
- New variables forgotten when function exits
Page 34
Inherited = Variables=20
- Variables defined before calling script available to script =
func_y () { echo "A is $A" return 7 } A=3D'bub' func_y if [ $? -eq 7 ] ; then ...- Try it: is a variable defined inside a function available to = the=20 main program?
Page 35
Functions = -vs- Scripts=20
- Functions are like separate scripts=20
- Both functions and scripts can:=20
- Use command-line arguments
echo First arg is $1- Operate in pipes
echo "test string" | ls_sorter- Return exit status
func_y arg1 arg2 if [ $? -ne 0 ] ...
Page 36
Libraries of = Functions=20
- Common to store definitions of favorite functions in a file=20
- Then execute file with
. file- Period command executes file in current shell=20
- Compare to C shell's source command
Page 37
=
Section 7: Miscellaneous =
Here Files=20
- Data contained within script
cat << END This script backs up the directory named as the first command-line argument, which in your case in $1. END- Terminator string must begin in column one=20
- Variables and backquotes translated in data=20
- Turn off translation with \END
Page 38
Example With = Here File=20
- Send e-mail to each of several users
for name in login1 = login2 login3 do mailx -s 'hi there' $name << EOF Hi $name, meet me at the water fountain EOF done- Use <<- to remove initial tabs automatically =
Page 39
Set: Shell = Options=20
- Can change Bourne shell's options at runtime=20
- Use set command inside script
set -v set +v set -xv- Toggle verbose mode on and off to reduce amount of debugging = output=20
Page 40
Set: Split a = Line=20
- Can change Bourne shell's options
set -- word1 word2 echo $1, $2 word1, word2- Double dash important!=20
- Word1 may begin with a dash, what if word1 is '-x'?=20
- Double dash says "even if first word begins with '-', do not = treat=20 it as an option to the shell
Page 41
Example With = Set=20
- Read a line from keyboard=20
- Echo words 3 and 5
read var set -- $var echo $3 $5- Best way to split a line into words
Page 42
=
Section 8: Trapping Signals =
What are = Signals?=20
- Signals are small messages sent to a process=20
- Process interrupted to handle signal=20
- Possibilities for managing signal:=20
- Terminate=20
- Ignore=20
- Perform a programmer-defined action =
Page 43
Common = Signals=20
- Common signals are=20
- SIGINTR sent to foreground process by ^C=20
- SIGHUP sent when modem line gets hung up=20
- SIGTERM sent by kill -9
- Signals have numeric equivalents
2 SIGINTR 9 SIGTERM
Page 44
Send a Signal =
- Send a signal to a process
kill -2 PID kill -INTR PID
Page 45
Trap Signals=20
- Handling Signals
trap "echo Interrupted; exit 2" 2- Ignoring Signals
trap "" 2 3- Restoring Default Handler
trap 2
Page 46
Where to Find = List of=20 Signals
- See file
/usr/include/sys/signal.h
Page 47
User Signals=20
- SIGUSR1, SIGUSR2 are for your use=20
- Send to a process with
kill -USR1 PID- Default action is to terminate process
Page 48
Experiment = With Signals=20
- Script that catches USR1=20
- Echo message upon each signal
trap 'echo USR1' 16 while : ; do date sleep 3 done- Try it: does signal interrupt sleep?
Page 49
=
Section 9: Understanding Command = Translation=20
Command = Translation=20
- Common translations include=20
- Splitting at spaces, obey quotes=20
- $HOME -> /users/us/freddy=20
- `command` -> output of command=20
- I/O redirection=20
- File name wildcard expansion
- Combinations of quotes and metacharacters confusing=20
- Resolve problems by understanding order of translations =
Page 50
Experiment = With=20 Translation
- Try wildcards in echo command
echo b* b budget bzzzzz- b* translated by sh before echo runs=20
- When echo runs it sees
echo b budget bzzzzz- Echo command need not understand wildcards!
Page 51
Order of = Translations=20
- Splits into words at spaces and tabs=20
- Divides commands at
; & | && || (...) {...}- Echos command if -v=20
- Interprets quotes=20
- Performs variable substitution
Page 52
Order of = Translations=20 (continued)
- Performs command substitution=20
- Implements I/O redirection and removes redirection = characters=20
- Divides command again according to IFS=20
- Expands file name wildcards=20
- Echos translated command if -x=20
- Executes command
Page 53
Exceptional = Case=20
- Delayed expansion for variable assignments
VAR=3Db* echo $VAR b b_file- Wildcard re-expanded for each echo
Page 54
Examples With = Translation=20
- Variables translated before execution=20
- Can store command name in variable
command=3D"ls" $command file1 file2 dir1 dir2...- Variables translated before I/O redirection =
tempfile=3D"/tmp/scriptname_$$" ls -al > $tempfile
Page 55
Examples = (continued)=20
- Delayed expansion of wildcards in variable assignment=20
- Output of this echo command changes when directory contents = change=20 (* is re-evaluated each time the command is run)
x=3D* echo $x- Can view values stored in variables with
set- Try it: verify that the wildcard is stored in x without = expansion=20
Page 56
Examples = (continued)=20
- Wildcards expanded after redirection (assuming file* matches = exactly=20 one file):
cat < file* file*: No such file or directory- Command in backquotes expanded fully (and before I/O = redirection)
cat < `echo file*` (contents of file sent to screen)
Page 57
Eval Command=20
- Forces an extra evaluation of command
eval cat \< = file* (contents of matching file)- Backslash delays translation of < until second = translation=20
Page 58
=
Section 10: Writing Advanced Loops=20
While loops=20
- Execute statements while a condition is true
i=3D0 while [ $i -lt 10 ] do echo I is $i i=3D`expr $i + 1` done
Page 59
Until loops=20
- Execute statements as long as a condition is false =
until grep "sort" dbase_log > /dev/null do sleep 10 done echo "Database has been sorted"- Example executes until grep is unsuccessful
Page 60
Redirection = of Loops=20
- Can redirect output of a loop
for f in *.c do wc -l $f done > loop.out- Loop runs in separate shell=20
- New variables forgotten after loop=20
- Backgrounding OK, too
Page 61
Continue = Command=20
- Used in for, while, and until loops=20
- Skip remaining statements=20
- Return to top of loop
for name in * do if [ ! -f $name ] ; then continue fi echo "Found file $name" done- Example loops over files, skips directories
Page 62
Break Command =
- Used in for, while, and until loops=20
- Skip remaining statements=20
- Exit loop
for name in * do if [ ! -r $name ] ; then echo "Cannot read $name, quitting loop" break fi echo "Found file or directory $name" done- Example loops over files and directories, quits if one is = not=20 readable
Page 63
Case Command=20
- Execute one of several blocks of commands
case "string" = in pattern1) commands ;; pattern2) commands ;; *) # Default case commands ;; esac- Patterns specified with file name wildcards
quit) ... qu*) ...
Page 64
Example With = Case=20
- Read commands from keyboard and interpret=20
- Enter this script 'case.sh'
echo Enter a command while read cmd do case "$cmd" in list) ls -al ;; freespace) df . ;; quit|Quit) break ;; *) echo "$cmd: No such command" ;; esac done echo "All done"- When you run it, the script waits for you to type one of: =
list freespace quit Quit- Try it: modify the example so any command beginning with = characters=20 "free" runs df
Page 65
Infinite = Loops=20
- Infinite loop with while
while : do ... done- : is no-op, always returns success status=20
- Must use break or exit inside loop for it to terminate =
Page 66
=
Section 11: Forking Remote Shells=20
Remote Shells =
- Rsh command
rsh hostname "commands"- Runs commands on remote system=20
- Must have .rhosts set up=20
- Can specify different login name
rsh -l name hostname = "commands"
Page 67
Examples With = rsh=20
- Check who's logged on
rsh spooky "finger"- Run several remote commands
rsh spooky "uname -a; time"- Executes .cshrc on remote system=20
- Be sure to set path in .cshrc instead of .login =
Page 68
Access = Control with=20 .Rhosts
- May get "permission denied" error from rsh=20
- Fix this with ~/.rhosts on remote system=20
- Example: provide for remote shell from spunky to spooky =
spunky % rlogin spooky spooky % vi ~/.rhosts (insert "spunky login-name") spooky % chmod 600 ~/.rhosts spooky % logout spunky % rsh spooky uname -a spooky 5.5 sparc SUNW,Ultra-1- May also rlogin without password: security problem! =
Page 69
Remote Shell = I/O=20
- Standard output sent to local host
rsh spooky finger = > finger.spooky- Standard input sent to remote host
cat local-file | rsh = spooky lpr -
Page 70
Return Status =
- Get return status of rsh
rsh mayer "uname -a" echo $?- Returns 0 if rsh managed to connect to remote host=20
- Returns 1 otherwise=20
- Invalid hostname=20
- Permission denied
Page 71
Remote Return = Status=20
- What about exit status of remote command?=20
- Have to determine success or failure from stdout or stderr=20
Page 72
=
Section 12: More Miscellaneous=20
Temporary = Files=20
- Use unique names to avoid clashes =
tempfile=3D$HOME/Weq_$$ command > $tempfile- $$ is PID of current shell=20
- Avoids conflict with concurrent executions of script=20
- Do not use /tmp!
Page 73
Wait Command=20
- Wait for termination of background job
command & pid=3D$! (other processing) wait $pid- Allows overlap of two or more operations
Page 74
=
Section 13: Using Quotes =
Quotes=20
- Provide control of collapsing of spaces and translation of = variables=20
- Try it: run three examples=20
- No quotes (variables translated, spaces collapsed)
echo = Home: $HOME Home: /users/us/freddy- Double quotes (no collapsing)
echo "Home: $HOME" Home: /users/us/freddy- Single quotes (no translation or collapsing)
echo = 'Home: $HOME' Home: $HOME- Try it: single quotes within double quotes
echo "Home = directory '$HOME' is full..."
Page 75
Metacharacters=20
- Characters with special meaning to shell
" ' ` $ * [ ] = ? ; > < & ( ) \- Avoid special meaning with quoting
echo 'You have $20'- Backslash like single quotes=20
- Applies only to next character
echo You have \$20
Page 76
Examples With = Quotes=20
- Bad command line:
grep dog.*cat file- Shell tries to expand dot.*cat as file name wildcard=20
- Use quotes to avoid translation
grep 'dog.*cat' file- Single quotes OK in this case because we don't need variable = translation
Page 77
More Examples = With Quotes=20
- Read name and search file for name
read name grep "$name" dbase- Single quotes not OK because we need variable translation=20
Page 78
Searching for = Metacharacters
- Bad command line: search for dollar sign
grep = "Gimme.*$20" file- Problem: shell translates variable $20=20
- Solution: use single quotes
grep 'Gimme.*$20' file
Page 79