HELP! (What's wrong with this sh scr - (nf)

rpw3 at fortune.UUCP rpw3 at fortune.UUCP
Tue Apr 24 10:17:46 AEST 1984


#R:eneevax:-11200:fortune:26900051:000:4575
fortune!rpw3    Apr 23 14:40:00 1984

Tutorial time, netters. All wizards "n" (or "j", as appropriate).
---------------------------------------------------------------------

There is quite a lot wrong with your script, but most of it comes from
(1) mixing 'csh' and 'sh' syntax, and (2) not having proper syntax
for shell variables.

+--------------------
| The error message I keep getting is, "unexpected newline on line 10".
| This is the line with the "if" statement.
+--------------------

I think it's the line before the "if", but let's look at the whole
thing closely.

+--------------------
| #! /bin/sh
+--------------------

You asked for /bin/sh, so we'd better stick with /bin/sh syntax, not /bin/csh.

+--------------------
| for i 
| do
| 	set $ANSWER=no
+--------------------

First serious problem: "ANSWER" is a variable, "$ANSWER" is its VALUE. Since
ANSWER hasn't been used previously, it is null. Hence this line actually
says "set =no" which (since no valid hyphen-option is seen), sets shell
variable "1" (value $1) to the word "=no", and clears (sets to null) the
rest of the arguments ($2, $3, &c.). (See the section on the "set" command
in the "sh" man page.) However, the range of the "for" loop has already
been evaluated, so this will not truncate the loop early.

As you will see below, this line is not even needed.

+--------------------
| 	head -20 $i
| 	echo -n 'Would you like me to remove '
| 	echo -n "$i"
| 	echo ' ?'
| 	set $ANSWER=$<
+--------------------

Two problems: (1) again, we have $ANSWER where ANSWER is needed, but (2) this
is not how /bin/sh reads from the keyboard. This should be "read ANSWER".
(For /bin/csh, it should be "set ANSWER=$<")

(Whichever shell you use, reading the answer in will overwrite the previous
value of ANSWER, so the earlier "ANSWER=no" has no effect beyond this point,
and therefore that whole line should be left out.)

This is probably where your error message is occurring, NOT on the "if"
line.  Because of the spurious "$", the shell saw "set =$<" (the variable
ANSWER is still null...), and parsed this as "set =$ < [missing filename]".
It then  complained because you didn't finish supplying a filename after
starting input redirection "<".  The "$" is not special here, since "<"
is not one of the characters that the Bourne Shell knows about after "$".

+--------------------
| 	if [ $ANSWER = yes -o $ANSWER = y ] 
+--------------------

What happens if a user types just <carriage-return> to your question?
ANSWER will again be null, and the "if" will read "if [ = yes -o = y ]"
which will produce the error "test: unknown operator 'yes'". (Since the
"[" is a link to the program "test".)

To guard against this, always (1) use double-quotes around your read-in
strings and (2) pad such strings with a leading character to keep them from
ever being null:

	if [ "X$ANSWER" = Xyes -o "X$ANSWER" = Xye -o "X$ANSWER" = Xy ]

By the way, since "[" runs the "test" program, experienced shell programmers
will use the "case" construct for simple pattern matching, as in:

	echo -n 'Question? '
	read answer
	case "X$answer" in
	Xy | Xye | Xyes)
		... whatever you want to do if yes ...
		;;
	*)
		... whatever you want to do if NOT yes ...
		;;
	esac

+--------------------
| 	then
| 		rm $i
| 	fi
| done
| 				Thanks in advance,
| 				Pravin Kumar
+--------------------

All in all, I suggest a good slow careful reading of the "sh" man page,
followed by the purchase of Kernighan & Pike's "The UNIX Progarmming
Environment", and reading and PRACTICING of the shell programming examples
found there.

Rob Warnock

UUCP:	{ihnp4,ucbvax!amd70,hpda,harpo,sri-unix,allegra}!fortune!rpw3
DDD:	(415)595-8444
USPS:	Fortune Systems Corp, 101 Twin Dolphin Drive, Redwood City, CA 94065

p.s. A slightly cleaned up version of your script follows:

+--------------------
| : 'vrm - verbose "rm" - Shows first of each file, asks if o.k., and removes'
| case $# in
| 0)
|	echo 'Usage: vrm files...'
|	exit
|	;;
| esac
| for i 
| do
|	echo "----- $i -----"
| 	head -20 $i
|	echo '-----'
| 	echo -n "remove $i (yes, no)? "
| 	read answer
| 	case "X$answer" in
|	Xy | Xye | Xyes)
|		rm $i
|		echo "$i removed"
|		;;
|	*)
|		echo "$i not removed"
|		;;
|	esac
| 
| done
+--------------------

p.p.s.

Note that everything after the "head -20" can be replaced with "rm -i $i".

+--------------------
| : 'vrm - verbose "rm" - Shows first of each file, then calls "rm -i"'
| case $# in
| 0)
|	echo 'Usage: vrm files...'
|	exit
|	;;
| esac
| for i 
| do
|	echo "----- $i -----"
| 	head -20 $i
|	echo '-----'
|	rm -i $i
| done
+--------------------



More information about the Comp.unix mailing list