You are on page 1of 30

{\rtf\ansi\deff0\ansicpg1252

{\fonttbl
{\f0\froman times new roman;}}
{\colortbl\red0\green0\blue0;}
{\info{\author ��}}
\jexpand\viewkind1\viewscale100
\paperw12240\paperh15840\margl666\margr133\margt666\margb173
\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-333\slmult0
\fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-333\slmult0
\fs24\cf0\f0\charscalex100 {
1}\par\pard\li2626\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li2626\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li2626\ri0\sl-466\slmult0
\fs40\cf0\f0\charscalex100\b {Unit-7}\b0 \par\pard\li1613\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1613\ri0\sl-533\slmult0 \fs40\cf0\f0\charscalex100 {Shell
Programming}\par\pard\sect\sectd\sbknone\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-426\slmult0
\fs18\cf0\f0\charscalex100\b {PROGRAMMING IN THE BOURNE AND THE C-SHELL}\b0
\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0
\fs20\cf0\f0\charscalex100 {You can use the Shel as a programming language. The C-
Shel has al the usual language }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {constructs like sequencing, looping, decisions,
variables, functions and parameters. In this }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {section we wil look at these abilities of
the Shel , although regretful y not in complete detail.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{To look closely at the C- Shel 's capabilities would require a block in itself.
That is why as usual }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {we wil only take a few portions in detail and leave
you to the documentation for the rest. As with }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {any other programming language, the key to mastering
the C-Shel is practice. Keep writing Shel }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {programs Whenever needed and you wil soon feel
comfortable with them.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {When you
have written some complex Shel programs you wil realise that some UNIX
utilities }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {which
you might have thought were useless, are actual y very important and useful. Sed is
a good }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {example of
such a utility.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Shel
programs are very often cal ed shel scripts. By the way a She,, is a program like
any other, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {which
means that there can be different shel s. Actual y there are some other popular
shel s, of }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {which
the Bourne shel and the Korn shel are quite likely to be available at your instal
ation. The }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Bourne
shel was the first shel . in fact, and is sure to be there on your
machine.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {If you look at a UNIX machine, you can
think of it as being composed of several layers. At the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {lowest layer is the hardware which does al
the physical tasks and without which there would be }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {no computer and no LNIX. Above that is the
UNIX kernel which is the core of the operating }\par\pard\li1133\ri0\sl-240\slmult0
\fs18\cf0\f0\charscalex100 {system and does memory management, device handling and
al the other mundane tasks needed }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {to make the hardware easily usable by us. The UNIX
commands and utilities}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {come next.
At the top is the Shel which can be considered to be the outermost layer and which
}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {enables us to run
the utilities and other UNIX commands. You can construct higher
application }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {layers
of your own which run above the Shel . Although we have talked of the Shel as
being a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {different
layer, it is as much a program as any of the UNIX utilities. For that matter even
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {kernel is a
set of programs.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {We have
been referring to the Shel 's activities in the previous units, mainly when talking
of wild }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {cards. We
start our description of the C-Shel with this subject.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{While the C-Shel is very useful and has many features, there are some things that
are easier to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {do
in the Bourne shel . Moreover many system and third party shel scripts are written
in the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Bourne shel
. So in this unit we wil look at both these shel s.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0
\fs20\cf0\f0\charscalex100\b {WILD CARDS}\b0 \par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {Wild card
characters are characters which can stand for characters other than
themselves, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{somewhat like a joker in a pack of cards (the joker has no intrinsic meaning by
itself). A judicious }\par\pard\li1133\ri0\sl-226\slmult0
\fs18\cf0\f0\charscalex100 {use of wild card characters can make many commands easy
to issue by saving a lot of typing and }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {preliminary research.<P. Suppose you have been writing
a series of programs for enciphering }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {text. You have been cal ing them cph0l.C, cph02.C and
so on. You suddenly realise that you }\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-266\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\m
arglsxn666\margrsxn133\margtsxn666\margbsxn173\cols2\colno1\colw2280\colsr-
0\colno2\colw9160\pard\li1133\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-
7}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {
2}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {have been
doing this in the directory ~/khanz/crypt, while actual y these programs are for
a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {particular
project and you would like them in the directory ~/khanz/crypt/knapsack. Al you
have to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {do, to
rectify the situation is to move your programs to the correct directory after
creating it So you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{start off}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% cd ~/khanz/crypt}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{% mkdir knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph0l.C knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph02.C knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph03.C knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Soon you
get sick of typing almost the same thing again and again, which can easily happen
if }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {you have just
19 programs. You could stop as soon as mv reported a non-existent source file,
but }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {if you had
mistakenly left gaps while naming the files, you could not be sure that there were
no }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {more files. To
be sure, you would have to do an Is to look at the directory listing first. Then
you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {would have to
keep issuing mv commands until you succeeded in moving al the files. Here
you }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {would probably
need to keep checking the directory listing from time to
time.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {It is much less effort if you use wild
cards. Just say the fol owing after you have made the sub-}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100
{directory you want}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph??.C knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {The ? is a
wild card character and can stand for any single character including itself, much
like }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {the. in vi.
So cph??.C expands to cph fol owed by any two characters, fol owed by C. This is
quite }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {likely al
you need to say. If it does not work, it can only be because you named some of
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {programs
differently, thus invalidating our basic assumption, not because of a problem with
wild }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{cards.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {The ? metacharacter implies the existence
of exactly one character in that position. So cph1.C }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {wil not be matched by the command above.
You need to remember this. If, for example you had }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {named the files cphl.C, coh2.C, ...,
cph10.C, cph11.C and soon, then the command.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph??.C knapsack}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {wil leave
any files from cph1.C to cph9.C in the same directory as before. You can move
them }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {too with
case}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% mv cph?.C
knapsack}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {But what if your naming convention only
started the filenames with cph and al owed any number }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {of characters after that (this is quite
common)? Is there no easy way out? Even assuming a limit }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {of 14 characters in the filename (some
systems do not have a limit), and counting 2 fixed }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {characters at the end and 3 at the
beginning, you are left with upto 9 characters to look for in
the }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {middle. So you
can use the fol owing method}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% mv cph.C
knapsack}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph?.C knapsack}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {%
mv cph??.C knapsack}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{% mv cph???.C knapsack}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {% mv cph????.C knapsack}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {% mv cph?????.C
knapsack}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
3}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% mv
cph??????.C knapsack}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{% mv cph???????.C knapsack}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {% mv cph?????97?.C knapsack}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {% mv cph?????????.C
knapsack}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {While this is much simpler than looking at
the directory listing and then issuing mv commands, it }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {entails some labour anyway. This was the
time to say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {%mv cph*.C
knapsack}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {You have now seen the * metacharacter,
which matches any sequence of characters in that }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {position, including the situation where
there is no character at al . So the * here matches from 0
to }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {9 characters
(more if required), and those characters can be any character including the *
itself, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {except a
leading period.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {You cannot
at this stage wonder how to put a ? or a * in a filename, except that in the Bourne
}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {shel a command
like}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ vi cph*.C}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{is not expanded unless there is at least one filename around which satisfies the
expansion of the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{command. So if there is a directory which does not have any file whose name starts
with cph, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then a
filename cph*.C is created. where the * is taken literal y. In other cases, you can
create }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {such a file
by}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {% vi cph\\*.C}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {escaping
the * with a\\ as usual. A? can be put into a filename in the same way. But it
would be a }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {good
idea to avoid such characters in filenames so that there is no
confusion.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs20\cf0\f0\charscalex100\b {SIMPLE
SHELL PROGRAMS }\b0 \par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0 \fs20\cf0\f0\charscalex100 {We spoke
earlier about how we could use the C-Shel as a programming language. Before
we }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {see how to
write programs using al the capabilities of the Shel , we wil look at some simple
shel }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {scripts to
il ustrate the concept.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Suppose
you, khanz, are working on your cryptography project in a directory
~/prj/crypt/pkc/src }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{where your source files are located. This is where you are most of the time. But
sometimes you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {have
to stray away from here to look at documentation which you have stored elsewhere,
or to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {some other
project you are working on. It is cumbersome to type out the whole pathname of this
}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {directory to
search it. Let us create a shel script in your home directory to do the job. Use
vi to }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {create a
rile wd}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% cat wd}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{Is ~/prj/crypt/pkc/src}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Now go to
some distant directory like /usr/include/sys and type}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{% wd}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Nothing happens, or rather you are told
that wd cannot execute. This is because you do not have }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {execute permission on the newly created
file wd (unless you have set the umask to al ow it). So }\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-453\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\ma
rglsxn666\margrsxn133\margtsxn666\margbsxn173\cols2\colno1\colw2280\colsr-
0\colno2\colw9160\pard\li1133\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-
7}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {
4}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {we need to
acquire this permission, which is easy because we own the
file}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% chmod 755 ~/wd}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{Now you can try typing ~/wd to execute the file. You could also have
tried}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% csh ~/wd }\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{which would also have executed. We have looked at this in the discussion of the
mail command, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {and
we wil look at in some more detail later.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Note that
if you just type}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {%
wd}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {in a distant directory, you wil not be able to execute
the command. This is because when the }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {Shel is given a command to execute, it looks for the
command in different directories in a fixed }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {sequence. The first directory searched is the current
directory, fol owed by /bin and /usr/bin.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {These are
only typical settings and can be control ed by you in a manner which wil be
soon }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {explained.
Since wd is not in any of these directories. UNIX does not find the command
and }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {complains.
Until you learn how to fix this, you can continue with
~/wd.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {If you consider it careful y, you wil
realise that you have now created a UNIX command of your }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {own. If you give others execute permission
on the file, anybody else could type wd and search }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {your directory.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{While that is probably not what you would want to encourage, you could create more
general y }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {useful
shel scripts presently. This is at the core of the UNIX philosophy of building on
the work of }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{others. Once somebody has written a command, you do not have to write it again.
But if you want }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {to
do something slightly different. you can, probably use the available command and
use other }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {commands
to modify its effect. We wil see examples of this by and
by.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {You have to be careful when you write
general y useful shel scripts. While you can afford to be
a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {wee bit sloppy
when you are writing for yourself, and can sometimes leave weaknesses in
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {command
because you know of them and wil take care not to use the command in
those }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {situations,
you cannot release a command for public use so casual y. Most instal ations have
a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {set of shel
scripts and programs in the usual programming languages
available.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {These are local y developed or acquired
programs which are found to be useful at that site. You }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {should learn to use them to advantage
before you try to write your own commands for some task. }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {Such utilities are usual y placed in
/usr/local/bin. If you have special purpose utilities that are
not }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {generalised
enough to go there, you can col ect them in your directory tree in a place like
~/bin.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {Let us now look at some of the pitfal s a
novice might come across when writing his own shel }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {scripts. Suppose you want to have your Is
command work like Is -al and you do not want to type }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {out the ful command every time. So in your
home directory you can create a file Is}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% cat
Is}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {Is -al}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {and make
it executable. Now when you try to look at the directory
listing}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% Is}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-386\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
5}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {you get a
blank look from UNIX and you wil not need to interrupt the command. This is
because }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the
command is cal ing itself in an infinitely recursive fashion. You wil therefore
need to change }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{your command}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% cat Is}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{/bin/Is -al}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {so that it cal s the real Is. That is how
you can hope to get any work done, because your Is relies }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {on the system's Is command to get you the
directory listing.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {This wil
now work, but not if you try a command like}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% Is
prj/crypt}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {You wil stil get the listing of your
current directory. That is because we have rot given our Is
the }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {ability to
recognise command line arguments. We wil soon see how to do that. ntil then, our
ls is }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {not going to
be very useful.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0
\fs20\cf0\f0\charscalex100\b {VARIABLES}\b0 \par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {We now
come to the basic features of the Shel programming language. Let us see how
variables }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {can be
defined and used in the C_ Shel . In the course of this discussion we wil solve
many other }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{mysteries which we have been putting off til now, like how to make UNIX recognise
a command }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {in some directory, how to change the UNIX prompt, how
to customise your environment when }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {you login and several other
things.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {It is easy to define and set a variable in
the C-Shel and look at its value. For example, you can
try}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% set vehicle =bus}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{This creates a Shel variable cal ed vehicle and sets its value to "bus". To look
at the value say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% echo
$vehicle}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {bus}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {If we have
another variable cal ed vehicle1 with a value car, we can
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% echo $vehicle and
$vehicle1}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {bus and car}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{The echo command has been given three arguments here of which the first and third
are shel }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{variables and the second is a constant string. The command dutiful y prints out
the values of the }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{variables and the constant is unchanged.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {But if you
want to now define another variable adj to be "business", then you cannot
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% set adj
=$vehicleiness}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% echo
$adj}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-466\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
6}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Since
there is no variable cal ed vehicleiness, this sets the value of adj to a nul
string. You can }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{achieve the effect you want by enclosing the available variable in
braces}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% set adj=$ (vehicle\}
iness}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% echo $adj}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{business}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {If a variable is to be set to a string
containing spaces, then the string needs to be enclosed
in }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {quotes, single
or double}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% set greeting = "How do you
do"}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% echo $greeting}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{How do you do}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Once you
have defined a variable you can freely use its value. So if you have
said}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% set Cat= "cat
~/.exrc"}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {then you can always print out your exrc
file by saying}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {%
$Cat}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {set numberset
tabstop=4}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {set terse}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{Another way of setting Shel variables is by making them equal to the output of a
command. To }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {use
the output of a command in the Shel you have to put the command in the accent
grave, or }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {back
quotes.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Similarly you could set a variable to the
current directory}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% set
dir--'pwd'}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% echo $dir}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{/usr/khanz/prj/crypt/src}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {We wil
now see how to pass arguments to Shel scripts so that they are not ignored when
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {command is
executed. You have seen how the private Is command you had created did not
take }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {any arguments
into consideration. The command was therefore not of much use. You wil
now }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {learn to
rectify this shortcoming. }\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {In fact
many of the other toy Shel scripts we have written so far are al but useless if
we cannot }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {get them
to accept arguments and act on them. For example the Cat command given as
an }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {exercise would
be much more useful if one could ask it to print the file of one's choice in
upper }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {case rather
than some fixed file.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {You can
make a shel script refer to command line arguments by using the notation $n for
the nth }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {argument.
Only 9 arguments can be so accessed. These are also cal ed positional
parameters }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {because
they are referred to by their position on die command line instead of by name. The
name }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {of the shel
script itself can be referred to as $0. So you can write an improved version of
your Is }\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{command}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% cat ~/is}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{/bin/Is -al $1}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100
{
7}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {This version wil accept the first argument given to
it. So if you say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% ~/Is
/usr/khanz/prj/cryt/src}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {you wil
get a long listing of al files in that directory. But even this fails if you give
a second }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {argument
or more arguments. Try the fol owing command}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% ~/Is
/usr/khanz/prj /usr/khanz/doc}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Now only
the first argument is recognised and the second is ignored. Wel , let us have an Is
}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {which recognises 9
arguments. So we get into vi and change our command to}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{% cat ~/Is}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {/bin/Is -al $1 $2 $3 $4 $5 $6 $7 $8
$9}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {But what if there arc more than 9 arguments? Are we
doomed to have only such a limited version }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {of our Is? Fortunately in this case you can easily
solve the difficulty by using the notation $* which }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {stands for al the arguments, whatever the
number. This way we can get around the limitation of }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {being able to handle only 9 positional
arguments. Thus we now have a ful blown Is command of }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {our own}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% cat
~/Is}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {/bin/Is -al $*}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{We can also find out the number of arguments by saying $#. This excludes $0, the
name of the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {shel
script itself. So you can write a simple command to count the number of arguments
given to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {it. Such
a capability is also useful when you want to write production shel scripts which
need to }\par\pard\li1133\ri0\sl-226\slmult0 \fs18\cf0\f0\charscalex100 {take care
of error checking. for instance, ensuring that the shel script works only if it is
cal ed with }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {the
proper number of arguments, or even performing a different action depending on the
number }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {of
arguments passed to it.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% cat
count}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {echo $#}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% count
apple boy cat dog elephant fish}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{6}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {There is also a shift command which has the effect of
shifting its arguments such that each. }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {positional parameter gets the value of the next one,
and the original value of the first parameter is }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {discarded. Using this facility you can deal
with a situation where there are more that 9 positional }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {arguments. Let us see a simple
example}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% cat showargs}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$1
= $1'}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-320\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
8}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
266\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$2 = $2'}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$3
= $3"}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {echo"\\$4 = $4'}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$5
= $5'}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-320\slmult0 \fs20\cf0\f0\charscalex100
{echo "\\$6 = $6'}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
306\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$7 = $7'}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-320\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$8
= $8'}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100
{echo "\\$9 = $9'}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
320\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$10 = $10"}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{The echo command can be given the -c argument to suppress dw printing of the new
line }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {character, -n
for inserting a new line character, -f for form feed and -t for tab characters. In
the C- }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Shel the
-n option suppresses the printing of the new line. Any variable enclosed in
double }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {quotes are
substituted for their actual values, but anything in single quotes is not
altered. }\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {If you want a character literal y within
double quotes, you can use a backslash to escape it.
Within }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {single
quotes you would not need the backslash but then you would not be able to get the
values. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Quotes of
one kind can be used to enclose quotes of the other kind. Now we can understand the
}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {output of
showargs}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% showargs apple boy cat dog elephant fish
girl house }\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$1 = apple}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$2 = boy}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$3 = cat}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$4 = dog}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$5 = elephant}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$6 = fish}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$7 = girl}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$8 = house}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {$9 =inkpot}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$10=apple0}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{You can see that $10 has been interpreted as $1 fol owed by the literal 0. To take
care of this we }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{wil alter showargs (only the him lines are shown)}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{% cat showargs}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-280\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\
sl-333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{...}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {
9}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\pard
\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {echo "\\$9 = $90}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{shift}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {echo "\\$10 = $9*}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{Now the output of the previous command changes to the fol
owing}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$9 = inkpot}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{$10=jug}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {There are some variables in the Shel which
are predefined, which means that their values do not }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {have to be set by you. When you login those
variables are created and set appropriately. }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {However many of them can be altered
subsequently. You can see a list of al variables
currently }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {defined
together with their values by saying}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {%
env}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {printenv has the same effect. You should
check out your environment with the env command. }\par\pard\li1133\ri0\sl-
226\slmult0 \fs18\cf0\f0\charscalex100 {You can easily make out the meanings of
most of them because the names are suggestive of the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {meaning. Thus LOGNAME is your login name,
HOME is your home directory and so on.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {You can
also use the set command to display the values of al variables set in the current
shel . }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {For example
the default C-Shel prompt is the percentage sign %, stored in the shel
variable }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {prompt.
This is the key to customizing your environment when you login, as we have always
been }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {promising you
could.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {In the C-Shel every time you login, UNIX
looks for a file in your home directory cal ed ".login".
If }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {this file
exists then , commands in that file are executed before you are presented with your
first }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {system
prompt. 'Mere is a corresponding file which is executed when you log out of the
system. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {ibis file
is cal ed ".logout".}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Suppose
you usual y work in Your /usr/khanz/Prj/crypt/c++/src directory. You would like to
be }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {placed in this
directory automatical y every time you login. Al you have to do is to put
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {fol owing line
in your .login file}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {cd
prj/crypt/c++/src}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Since you
wil anyway reach your home directory. we have given a relative pathname to reach
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {desired
directory. If you want your UNIX prompt to give you the number of the command you
wil }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {be executing,
you can say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {set prompt=\\!\\
%\\}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {The exclamation mark stands for the command
number and we escape it to prevent it from being }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {evaluated immediately, which would make the
prompt constant. Now you see a prompt like}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {1%
pwd}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {/usr/khanz/pd/crypt/c+
+/src}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {2%}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-386\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
10}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Every time
a command is executed the command number increases by one and this shows up
on }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {your prompt.
Commands separated by semicolons are considered to be one command, as
you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{know.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {There are some other convenient features
which can be set up for a pleasing environment. Of }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {course these are a matter of individual
taste, so we wil talk of those done by most people. You }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {can always choose what you feel congenial
for yourself. If you say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% set
ignorecof}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {then you wil have to " out "exit' or
"logout in order to terminate your login session, a mere ^D
wil }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {result in a
message}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {Use "logout" to
logout}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs18\cf0\f0\charscalex100 {This is useful to prevent accidental log
outs because ^D can get typed by mistake while it is much }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {more unlikely you wil " a ful word when
you do not need it. Another safety feature is to say}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{% set noclobber}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs18\cf0\f0\charscalex100 {If this
variable is set then an operation which would otherwise overwrite an existing file
silently wil }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{refuse to do with the message}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {file
exists}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {Both these variables need only be set, and
no values need to be put in them. The C-shel }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {distinguishes between variables whose value
is nul and those not defined at al .}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {A very
convenient feature Of the C-Shel (this is absent in the Bourne Shel ) is the
facility of a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{command history. If you set the variable history then the last commands you typed
in can be }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {executed
very easily without your having to type the complete command
in}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {% set history=100}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {wil al
ow you to access dw last 100 commands you typed. If you want to see al of them,
just say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% history}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{and the last 100 commands wil be displayed. You can set history to a smal er
value of about 20, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{this is probably sufficient most of the time.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{If history is set, you can run a Previous command in two ways. You can
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {%!56}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {and the
56th command of your session (not 56th in the current history) wil be executed.
This }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {includes al
command line arguments, redirections, pipes and al other special characters it
might }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {have
contained. Usual y when you want to repeat some command you do not know its number,
}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {but you of course
know what the command was. Let us say you ran a longish sed command
to }\par\pard\li1133\ri0\sl-226\slmult0 \fs18\cf0\f0\charscalex100 {perform some
action on a file and now you need to do it again after some change has occurred
to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the input. You
need to say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% !sed}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{and the last command starting with sed wil run. You do not have to give the whole
word sed. any }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{number of characters which make the command unambiguous wil do. So if you have
not run any }\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
11}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {command
starting with se after you ran sed, you can say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {%!
se}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {and if you have not run any command with s itself, you
could have abbreviated it stil further. But }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {remember that the last command is the one
that wil be run. If there were a command like sedate }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {and if you had run it after sed, then the
above abbreviated commands would have run it instead }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {of sed.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {There are
ways of editing the command before running it but it is usual y simpler to retype
it again }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {in that
case. Also the abbreviated command can be used to run another command containing it
}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {like
this}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {34% sort datafile}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{....}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {48%!34 newfile}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{sort datafile newfile}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {There is
one aspect of the Shel which we have mentioned earlier but which needs
elaboration. }\par\pard\li1133\ri0\sl-226\slmult0 \fs18\cf0\f0\charscalex100
{Whenever a command is executed it does so in a child shel which inherits the
environment of the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{parent shel . If you want variables you have set to have effect in child shel s as
wel , you need to }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{say setenv rather than just set. Otherwise those variables wil not be passed onto
child shel s. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {You
can easily try this out.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Another
thing is that you cannot make a change to your login file, run login and have the
changed }\par\pard\li1133\ri0\sl-240\slmult0 \fs18\cf0\f0\charscalex100
{environment. This does not mean that the commands are not run. The point is that
they are run in }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {a
child shel and as soon as the command terminates, you are back in the parent shel
where }\par\pard\li1133\ri0\sl-226\slmult0 \fs18\cf0\f0\charscalex100 {there is no
effect of anything that happens in a child shel . The environment is passed
downwards }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {to child
shel s but cannot be passed back to parent shel s. To make a change to your login
and }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {have it take
effect immediately, you should say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {% source
login}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {This runs the login file exactly as if you
had typed out each command at the prompt instead of }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {executing the commands in a child shel . To
be precise, the source command temporarily (for the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {duration of the command) redirects the
standard input of the shel to come from the file instead
of }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {from the
terminal. This command can of course be given any shel script as an argument and
is }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {not confined to
login.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs18\cf0\f0\charscalex100 {One more feature which is sometimes useful
in the C-shel is the repeat command. You can run a }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {command several times repeatedly by
saying}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% repeat 17 echo hel
o}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {and you wil find that the echo is executed
17 times.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
306\slmult0 \fs20\cf0\f0\charscalex100 {You can use the alias feature of the C-shel
to abbreviate commands (strictly to give them another }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {name). Thus if you frequently use Is -al,
you can say something like}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
306\slmult0 \fs20\cf0\f0\charscalex100 {% alias 11 is -al}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
12}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Now
whenever you want to use Is -al, just say l and you wil get the same effect. You
can give }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {arguments
to l and they wil be taken as additional arguments to Is -al, the actual
command. To }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {turn
this feature off, just say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {% unalias
11}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {Usual y such aliased commands are placed in one's
.login file so that they are in effect }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {automatical y as soon as one logs
in.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-386\slmult0 \fs20\cf0\f0\charscalex100\b
{PROGRAMMING CONSTRUCTS}\b0 \par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0 \fs20\cf0\f0\charscalex100 {So far the
shel scripts we have written have been nothing but a sequence of commands
which }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {we could
very wel have given from the system prompt itself in most cases. They would
have }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {been useful
but not very much so, if the capabilities of the Shel were confined to setting
variables }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {and
printing their values.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {What makes
the shel Powerful is that we can use it as a programming language. it has al
the }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {constructs
needed to write a program, and in this section we shal look at
them.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {While the C-Shel is very convenient to use
on the command line because of its greater set of }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {features suitable for interactive use, the
Bourne shel is sometimes more convenient in some }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {ways when you want to write a shel script.
For this reason in this section we wil discuss mainly }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {the Bourne Shel and wil give the C-Shel
features sometimes, because of lack of space. }\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{As always, you are regretful y referred to the UNIX documentation for the details
of how to }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {program
in the C-shel . But remember that even if you use the C-shel for interactive
commands, }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {you can
always run a Bourne shel by giving a: by itself on the first line of the shel
script.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {This is also the default shel used for
shel scripts. So even if you omit the: the script wil
be }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {assumed to be a
Bourne shel script and wil be run as such by default. You can run a C-
shel }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {script by
putting a # instead of a: on the first line.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {In the fol
owing examples you can distinguish between the Bourne rind the C-shel scripts by
the }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {prompts used
($ for the Bourne shel and % for the C-shel ), and by the: or the # in the
scripts.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Let us first look at the looping constructs
available. There is a for loop which works like this in
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Boume shel ,
which has a default $ prompt}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat
mkupper}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{:}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {for i in
'Is'}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{do}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {tr [a-z]"[A-Z]'
$i $i.up}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{done}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {The C-shel version Of the sane script wil
be like this}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {% cat mkupper}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {#}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {foreach i ('Is')}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {tr '[a-z]' ' [A-Z]' $i $i.uP}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {end }\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-466\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
13}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {This
script wil change every file in the current directory to upper case and write it
out with the .up }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{extension. The i is a variable we use to effect to our plans, and it serves as a
loop variable. The Is }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {command can have several values and the loop is
executed for each of the values in turn. For }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {every value, the file is converted to upper
case and written out with a .up" extension.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {When al
the files have been processed, the loop terminates. We can write another version of
this }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {script which
wil convert only the flies specified as arguments to it into upper
case.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat mkupper.arg}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {for i in
$*}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{do}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {tr '[a-z]' '[A-
Z]' $i $i.up}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{done}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Here we can give the script any number of
arguments and every file we specify wil be converted }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {into upper case. Actual y in this case we
can omit the in and the first line can be}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {for
i}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {which wil work just as the previous line.
One can also execute loops with the while or until }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {constructs, which have the usual
meanings.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ cat mkupper.1}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {:}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {while test $# -gt 0}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {do}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {tr '[a-z] ' ' [A-Z]' $1 $ I.up}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {shift}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {done}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Here the
while loop is performed as long as there are some arguments left. The tr operation
is }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {done only on
the first argument every time. The shift then renumbers the arguments and
throws }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {out the
first argument (which has already been dealt with). When there are no arguments
left the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {loop
terminates. The C-shel has its own version of the while
loop.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {The until loop is exited only when the
condition becomes true. This construct
is not available in }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {the C-shel , but you can get around that quite easily
by negating the condition of a while loop. Let }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {us look at the version with this loop
construct}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat mkupper.2}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {:}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {until test $# -eq 0}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {do}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {tr '[a-z]' '[A-Z]' $1 $1.up}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {shift}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {done}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Now the
loop is terminated when the number of arguments is 0. Of course since we
have }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {changed the
condition to be tested, the effect of this is the same as in the while loop
case.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {In the looping examples above, we have been
using the test operation. which can be used in the }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Bourne shel to test various conditions.
lie operation returns a 0 if the test is passed and a non }\par\pard\li1133\ri0\sl-
226\slmult0 \fs18\cf0\f0\charscalex100 {zero value otherwise. We wil quickly
describe the conditions which can be tested. Let us first
look }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {at the
relational operators on positive or negative integers. You can
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-320\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
14}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
266\slmult0 \fs20\cf0\f0\charscalex100 {test a -gt b (for checking if a
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {test a -ge b (for checking if a =
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs18\cf0\f0\charscalex100 {test a -eq b (for checking if a =
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {test a -ne b (for checking if a !=
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {test a -It b (for checking if a
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {test a -le b (for checking if a
b)}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {In the translation examples above, we have used this
numeric test to stop the loop when there }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {are no arguments left. Suppose there were no arguments
given to the command mkupper when it }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {was run. One could exit silently, or print an error
message, or use the standard input in such a }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {case. The examples given al exit silently
if there are no arguments. Let us see how to change }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {this behaviour.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-306\slmult0 \fs20\cf0\f0\charscalex100 {$ cat
mkupper.3}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{:}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {if test $# -eq
0}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then echo "No
files to translate!"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{exit}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{fi}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {while test $#
-gt 0}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{do}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {tr'[a-z]' '[A-
Z]' $1 $1.up}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{shift}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{done}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {The beginning of the script introduces to
the if statement, which is how a decision can be made in }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {the shel . We wil look at this statement
and its variants a bit later. The fl delimits the
statements }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {to be
performed if the condition is true. This script wil tel you if are no files to
translate and wil }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{put you back to the shel prompt if that happens. You can now easily write a
script which takes }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{input from the standard input if no arguments are supplied to the command when it
is invoked.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {We can now look at some of the tests that
can be performed on files. Here you can use ! as the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {negation operator to check for the inverse
of a condition.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {test -s
filename (does a non-empty filename exist?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {test -f
filename (is filename an ordinary file?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {test -d
filename (is filename a directory?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {test -r
filename (is filename readable?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {test -w
filename (is filename write able?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {The tests
for reading and writing are for the user running the script, that is, you can find
out if you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {can
read from or write to the file in question. Using these tests, we can make our
script more }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {robust
by checking if the files given as arguments exist}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{$ cat mkupper.4}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
320\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{:}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {
15}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {if test 5# -eq
0}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then echo "No
files to translate!"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{exit}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{fi}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {while test $#
-gt 0}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{do}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {if test -s
$1}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {then if test -f
$1}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then tr'[a-z]'
'[A-Z]' $1 $1.up}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{fi}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{fi}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{shift}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{done}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0
\fs20\cf0\f0\charscalex100 {Here we have used two if statements within .the while
loop to check for the existence of each file }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {given as an argument to the command. You
should expand this script to print an appropriate error }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {message whenever needed. Notice that the
actual action we are performing is confined to the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {one line tr command. It is the error
checking that is now taking up more and more of the
script. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {This is in
keeping with what happens in most programs, where error checking takes up a
large }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {part of the
production version of any software.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {You can
also compare two character strings as fol ows}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{test a = b (is string a the same as string b?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {test a !=
b (are the strings different?)}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {You can
also use test -z which is true if a string is nul , and test -n which is true if
the string is not }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{nul . Also, test by itself, if fol owed by a string, checks if the string exists.
You should now rewrite }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {the previous script to check for the absence of an
argument using the appropriate form of the test }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {operation.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{You can combine two tests with -a for an and operation (true if both the tests
pass) or -o for an or }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {operation (true if either of the tests pass). This can
be used to rewrite the scripts above with only }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {one if statement.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{The if statement itself is the same as in conventional programming languages. If
the condition }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {fol
owing the if keyword is true the statements that fol ow are executed. The body of
the if is }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{terminated with a fi. Suppose you want to write a script that wil take three
arguments. The first }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {two should be filenames that exist and the third is to
be a new file that wil hold the concatenation }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {of the upper case versions of the first two files. We
thus need to ensure that the first two }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {filenames exist and the third does
not.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {The if statement can have an else part
which is executed if the condition fol owing the if is
not }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {true. In such
a case the then is delimited by the else and the whole statement is delimited by
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {fi. ]be else
if construct is also available and can be combined as an elif keyword. In the C-
Shel , }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the
delimiter is the keyword endif and you can give any number of else
parts.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat Concat}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {:}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {if test $# -ne 3}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {then echo "Usage: $0 in-fi l in-fl2 ou-
fl"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{exit}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {elif test! -s
$1 -o ! -f $1}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then
echo "Invalid filename $ 1}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
373\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{exit}\par\column\pard\li0\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100 {
16}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {elif test! -s $2 -o ! -f
$2}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {then echo
"Invalid filename $2'}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {exit}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {clif test -s $3 -o -f $3}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {then echo "$3
exists"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{exit}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {else tr '[a-
z]' '[A-Z]' $1 tmp1}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{tr '[a-z]' '[A-ZI' $2 tmp2}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {cat tmp1 tmp2 $3}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {rm tmp1 trnp2}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {fi}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {The break
and continue statements are available with loops to come out of the loop and go
back }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {to the
beginning of the loop respectively.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {We can
also put comments in the Boume Shel by using a #. Al statements on a line fol
owing the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {#
including the # itself are ignored by the shel during execution. In complex shel
scripts it is a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{good idea to include comments explaining what the script does and how it
works.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {In the example above we used a multiple if
statement. In some situations it is more convenient to }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {use the case statement which is il ustrated
below. The example is a trivial one but does show how }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {the statement
works}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat showcase}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{case $2 in}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-320\slmult0 \fs20\cf0\f0\charscalex100
{upper) tr '[a-z]' '[A-Z]' $1 $I.UP;;}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {lower) tr '[A-Z] " [a-z]' $1 $
1.low;;}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {*) echo
"Invalid option';;}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{esac}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {This script takes two arguments. The first
is a filename which is converted into upper or lower }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {case depending on the second argument The
value of the second argument is checked against }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {the strings upper and lower. These strings
are delimited by a right parenthesis character). After }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {this is the body of statements that wil be
executed if a match is found. The shel metacharacters }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {can be used as strings to match against.
The whole case statement is terminated with a esac and }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {the action for each option is ended with
two semicolons.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {Now you
should try the fol owing variation of the script}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{$ cat showcase. 1}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{case $2 in}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {*) echo "Invalid option";;}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {upper) tr'[a-z]"[A-Z]' $1
$1.up;;}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {lower)
tr'[A-Z]"[a-z]' $1 $1.low;;}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {esac}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {This is
the same as the earlier one except that the * now appears first in the list of
strings to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {check
against. Since any string wil match this, this is the action that wil be taken
every time. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Thus
it is the first match found which is executed in a case statement. So the order in
which you }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {write
the matches in the body of the case is very important.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-346\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
17}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100\b
{INTERACTIVE SHELL SCRIPTS}\b0 \par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0 \fs20\cf0\f0\charscalex100 {So far we
have only looked at shel scripts which have not required an interaction with the
user }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {once started.
But the power of the shel does not stop at the constructs we have seen so far. It
is }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {possible to
take input from the user and take further action depending on it. You can thus
write }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {interactive
programs.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {To pass user input to a command inside a
shel script, we can fol ow the command with the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {notation &0. Although this is not necessary
and user input wil usual y get passed to the command }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {inside the script, this notation ensures
that this wil happen. Thus if in a shel script it is
necessary }\par\pard\li1133\ri0\sl-226\slmult0 \fs18\cf0\f0\charscalex100 {to cal
up vi in read only mode on some files (to al ow the user to examine them) you wil
want that }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the user
be able to use the view commands on those files. For this put the line which cal s
up vi }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {like
this}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {view $* &0}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{If you only want to accept input from the terminal directly for the shel program,
you say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {read x}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{and whatever you type wil get assigned to the variable
x.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0
\fs20\cf0\f0\charscalex100 {In one read statement you can have several variables to
which you can assign values. The first }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {response is assigned to the first variable, the second
response to the second variable, and so on. }\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
266\slmult0 \fs20\cf0\f0\charscalex100 {Responses are delimited by white space but
a new line does the assignment. If there are too }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {many responses, al the extra responses go
into the last variable. Using these features you can }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {write a menu driven shel program to
perform some tasks interactively. As you have seen, UNIX }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {commands are cryptic and do nor have a
helpful user interface. You could write a menu driven Is }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {program, for instance. Let us cal it
dir.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ cat dir}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {echo " 1 for long
listing"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {echo "2
for stream list'}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{echo "3 for single column list"}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {echo "Enter your choice \\c"}\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {read x}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{case $x in }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {1) Is
-1 $*;;}\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {2) Is -m
$*;;}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {3) Is -1
$*;;}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {*) echo
"Invalid choice"}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{esac}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {This script has a long way to go before you
could release it as a useful utility for beginners, }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {though. There is no error checking beyond
looking for a correct choice. You can try making this a }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {bit more robust. For instance, if the user
gives two input options, what wil happen?}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {This seems
like a good place to be talking of redirection. As you have seen in the
introductory }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {unit
of this block, you can redirect the standard output of a command to another device
or file. In }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the C-
shel which we had been looking at them, a command like}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{% Is -1 dir file}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-333\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
18}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {redirects
the standard output to the rile specified, dirfile in this case. 'Me standard
error. which is }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{not being redirected, is sent to the terminal screen as usual. To send the
standard error also to }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {error file we have to say}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{% Is -1 &error file}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Here both
the standard output and standard error are sent to error file. The task of sending
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {standard
output and standard error to different files is slightly more complicated, as we
have to }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {use sub-
shel s for this. Enclosing any command in parentheses executes that command in a
sub-}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {shel and as
soon as the command terminates you are back in the parent shel . We can
thus }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {redirect the
standard output to dirfile and the standard error to errfile at the same time
as fol ows}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {% (Is -1 dirfile)
&errfile}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {In the Bourne shel , on the other hand.
things are much more straightforward. To redirect the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {standard output alone,
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$Is -1 dirfile}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{This sends the standard output to dirfile and the standard error to the terminal,
as usual. To }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{redirect the standard error, say}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {$ Is -1 2
dirfile}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {Now the standard output wil appear on the
terminal and the standard error wil get redirected. }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {This is because in the Bourne shel you can
specify the file descriptor to be redirected by placing }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {it before the sign. The standard input is
assigned to file descriptor 0, the standard output to 1
and }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the standard
error is assigned to file descriptor 2 automatical y by UNIX. It should now be easy
for }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {you to
redirect the standard output and the standard error of a command to different
files.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ Is -1 dirfile 2
errfile}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {This command sends the standard output to
dirfile and the standard error of the same command }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {to errfile. To redirect both of them to the
same file you wil need to learn the idiom}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {$ Is -1
dirfile 2&1}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {which sends the standard error to the same
place as the standard output}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {You have
already seen in the first unit that in UNIX every device is actual y treated as a
file. We }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {wil look
at this concept in more detail in the next unit, but here let us see the behaviour
of a }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {special
device file in UNIX, cal ed the nul device. This is available in the device
directory just as }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{other devices are. Anything written out to the nul device simply disappears, and
it is thus an }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{infinite sink. Trying to read from the nul device always results in an end of
file. So if you want to }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {just discard the standard output, you just redirect it
to the nul device.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {$ Is -1
/dev/nul 2 errfile}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {This wil
throw away the output of the command but wil save the error messages in
errfile. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Likewise,
to discard the error messages but save the output, you could
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ Is -1 dirfile 2
/dev/nul}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {You now know how to suppress al output
from a command, but why would one want to do that? }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {Possibly if the command did perform some
operations on a device or disk file and you want it to }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {work silently without showing anything on
the terminal.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs24\cf0\f0\charscalex100
{ ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
19}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
266\slmult0 \fs20\cf0\f0\charscalex100 {$ mv file1 file2 /dev/nul
2&1}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {wil do the move without any terminal
output even if there are error messages from it. This is not
a }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {good example
though, for the command does not write to the standard
output.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
293\slmult0 \fs20\cf0\f0\charscalex100\b {ADVANCED FEATURES}\b0
\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-293\slmult0
\fs20\cf0\f0\charscalex100 {Let us now look at a few capabilities of the shel
programming language which you could consider }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {somewhat advanced. First we wil learn to
do arithmetic. This can be done with the expr }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {command}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {$ expr 2 +
3}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {5}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {Every
number and operator is a separate argument to the expr command. So al of them have
to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {be separated by
spaces. If you do not do so, you wil get an error. The command works only
on }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {positive or
negative integers. You can use the operators +, -, * for multiplication, 1 for
division and }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {% for
the remainder or modulo operation. Let us write a shel script to find the average
of the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {numbers
entered.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat average}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {:}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {total=0}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {count=$#}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {for i}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {do}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {total='expr $total + $i'}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {done}\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {avgl ='expr $total 1 $count'}\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {avg2='expr $total %
$count'}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {avg2='expr
$avg2 \\* 100 1 $count'}\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {echo "The average is $avgl.
$avg2"}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {We initialise the variables total and count
and compute the total by adding the value of each }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {argument until there are no more arguments.
Since we want a somewhat more accurate average }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {than to the nearest integer, we get the result to two
decimal places in a roundabout fashion.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {We first
find the integer part in avg 1. To find the decimal part, we find the remainder
after the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{division, multiply it by 1 00 and divide it by the number of entries. This gives
us the digits after the }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {decimal point. We then print out the answer by printing
out both the variables separated by a }\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {decimal point.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0
\fs20\cf0\f0\charscalex100 {Note that the * operator has to be escaped with a
backslash \\ otherwise it would have the special }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {meaning of al the files in the directory
to the shel . The expr command has some more }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {capabilities which we wil not discuss
here.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {Let us now look at another feature of the
shel , that of trapping interrupts and taking some action }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {depending on them. We wil il ustrate this
with a simple example. Suppose you have written a }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {shel script which interchanges the names
of the two files given to it as arguments. That is, if }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {there are two files cal ed chicken and egg,
then}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ interchange chicken
egg}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
306\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
20}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {renames
chicken to egg and egg to chicken. As a programmer you wil realise that to do this
you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {need to use a
temporary file. So a bare bones script (without any precautions or error
checking) }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {to do
the job wil look like this}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {$ cat
interchange}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {my chicken tmp}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{my egg chicken}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {my tmp
egg}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {There is a fair amount of checking this
script needs to do in order to be useful. The files must
both }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {exist and
there should not already be a file cal ed tmp. Assuming that these things are taken
care }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {of, what
happens if the user breaks the script in between? Depending on the actual instant
when }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {this is done,
you wil have a different situation, but certainly the effect you wished for wil
not have }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {occurred,
for one of the files wil be named wrongly and you wil have a tmp file lying
around. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {What you
want in this case is a way to prevent the user from interrupting the script until
it is }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{complete.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {In other, more realistic situations one
uses temporary files to hold temporary results. These
files }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {are deleted
in the script after they are no longer needed. If your script is interrupted you
would not }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {want
these files to be lying around.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {The shel
has a command cal ed trap which al ows you to achieve what you want. If you want to
}\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {prevent your
script from getting interrupted by the break key, you can
say}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {trap " 2}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{The quotes are the first argument to the trap command, which holds the command or
commands }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{(separated by;) to be executed whenever the script receives any of the signals
specified by the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{signal numbers in the subsequent arguments. You can look at the signal numbers and
their }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {meanings for
your system by examining the file "/usr/include/signal.h". A signal gets sent to
your }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {process wil
result in the action you asked for. Here since there is no command specified.
the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {effect wil be
to do nothing when the shel script receives the signal number 2, which is sent
by }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the break key.
To remove a temporary file you create, you can say instead}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{trap 'rm -f tmp$0$$ 2/dev/nul ; exit'2 15}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {$$ stands
for the current process number and tmp$0$$ is a reasonable way of almost
ensuring }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {that the
name of the temporary file you create wil not conflict with any other existing
filename. }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {Signal
number 15 is the default kil signal sent to a process when you kil it. However
note that }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {signal
number 9 is the kil signal which cannot be caught or ignored, and so it is no use
giving }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {signal
number 9 as one of the signals in your list.}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {In the C-
shel interrupts are handled differently and you should consult the documentation
for }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{details.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {One more useful feature is the ability to
give the input to a command which actual y takes its
input }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {from the
standard input normal y. You already saw how you can ensure that if any command
in }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the shel
script needs to take some input from the standard input you can supply that input
from }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {the keyboard
just as you would have done if the command had been run from the
terminal. }\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {But that is not always what you want or
need. Sometimes what is more important is to pass fixed }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {input to a shel command. For example you
might want to write a shel script which can be cal ed }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {with a filename argument, and which locates
and deletes al lines containing the word specified }\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-373\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan
Soni}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\p
ard\sect\sectd\sbkpage\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\margtsxn666\
margbsxn173\cols2\colno1\colw2280\colsr-0\colno2\colw9160\pard\li1133\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {Unit-7}\par\column\pard\li0\ri0\sl-
333\slmult0 \fs24\cf0\f0\charscalex100 {
21}\par\pard\sect\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn666\margrsxn133\par
d\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100 {as the
second argument. You already know how to do this in ed interactively. But how do
you }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {give this
input in the script itself?}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {To
il ustrate this with a simple example, let us take up the case where you want to
give a }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {message if
a person gives the wrong number of arguments. You could use echo, but let us
do }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {this with cat
instead.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {if test $# -ne 4}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{then}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {cat < this}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{What a stupid mistake}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{this}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {fi}\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100 {The
feature shown here is cal ed a here document and 'S introduced by the notation <.
The word }\par\pard\li1133\ri0\sl-240\slmult0 \fs20\cf0\f0\charscalex100
{immediately after the < is a label, and everything upto the first occurrence of
that label first thing }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {on a line by itself is taken to be input to the cat
command. So you can emped input for your }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {command in the shel script itself. It should be clear
that you cannot use this facility with }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {commands that do not read from the standard
input.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
253\slmult0 \fs20\cf0\f0\charscalex100 {You should now be able to write a shel
script that does the things we had talked of in the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {introduction to here documents. The only
part which needs to be done careful y is the input to the }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {ed command.}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{Before we end this unit, let us talk briefly about how to debug shel producers.
Although as }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{experienced programmers you wil not find it difficult to figure out where the
error lies by using the }\par\pard\li1133\ri0\sl-226\slmult0
\fs20\cf0\f0\charscalex100 {eco command judiciously, you could find the facilities
of the shel useful. For example you can run }\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {a file with the v option for vebose output,
wherein each command is printed and then executed. }\par\pard\li1133\ri0\sl-
226\slmult0 \fs20\cf0\f0\charscalex100 {This is like having an echo command after
every line.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
240\slmult0 \fs20\cf0\f0\charscalex100 {$ sh - v Concat}\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-253\slmult0 \fs20\cf0\f0\charscalex100
{Another option is -x, where every command line is shown with a + sign at the
beggining, and the }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100
{values of the variables before and after the command are printed. To be safe you
can decide to }\par\pard\li1133\ri0\sl-226\slmult0 \fs20\cf0\f0\charscalex100 {use
the - n (noexecute) option, where the commands are read but not
executed.}\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0
\fs18\cf0\par\pard\li1133\ri0\sl-213\slmult0 \fs18\cf0\par\pard\li1133\ri0\sl-
426\slmult0 \fs24\cf0\f0\charscalex100 {
ACME/Gulshan Soni}\par}

You might also like