The following periodic article answers in excruciating detail
the frequently asked question "Why shouldn't I program in csh?".
It is available for anon FTP from convex.com in /pub/csh.whynot .
*** CSH PROGRAMMING CONSIDERED HARMFUL ***
Resolved: The csh is a tool utterly inadequate for programming,
and its use for such purposes should be strictly banned!
I am continually shocked and dismayed to see people write test cases,
install scripts, and other random hackery using the csh. Lack of
proficiency in the Bourne shell has been known to cause errors in /etc/rc
and .cronrc files, which is a problem, because you *must* write these files
in that language.
The csh is seductive because the conditionals are more C-like, so the path
of least resistance is chosen and a csh script is written. Sadly, this is
a lost cause, and the programmer seldom even realizes it, even when they
find that many simple things they wish to do range from cumbersome to
impossible in the csh.
1. FILE DESCRIPTORS
The most common problem encountered in csh programming is that
you can't do file-descriptor manipulation. All you are able to
do is redirect stdin, or stdout, or dup stderr into stdout.
Bourne-compatible shells offer you an abundance of more exotic
possibilities.
1a. Writing Files
In the Bourne shell, you can open or dup arbitrary file descriptors.
For example,
exec 2>errs.out
means that from then on, stderr goes into errs file.
Or what if you just want to throw away stderr and leave stdout
alone? Pretty simple operation, eh?
cmd 2>/dev/null
Works in the Bourne shell. In the csh, you can only make a pitiful
attempt like this:
(cmd > /dev/tty) >& /dev/null
But who said that stdout was my tty? So it's wrong. This simple
operation *CANNOT BE DONE* in the csh.
Along these same lines, you can't direct error messages in csh scripts
out stderr as is considered proper. In the Bourne shell, you might say:
echo "$0: cannot find $file" 1>&2
but in the csh, you can't redirect stdout out stderr, so you end
up doing something silly like this:
sh -c 'echo "$0: cannot find $file" 1>&2'
1b. Reading Files
In the csh, all you've got is $<, which reads a line from your tty. What
if you've redirected stdin? Tough noogies, you still get your tty, which
you really can't redirect. Now, the read statement
in the Bourne shell allows you to read from stdin, which catches
redirection. It also means that you can do things like this:
exec 3<file1
exec 4<file2
Now you can read from fd 3 and get lines from file1, or from file2 through
fd 4. In modern, Bourne-like shells, this suffices:
read some_var 0<&3
read another_var 0<&4
Although in older ones where read only goes from 0, you trick it:
exec 5<&0 # save old stdin
exec 0<&3; read some_var
exec 0<&4; read another_var
exec 0<&5 # restore it
1c. Closing FDs
In the Bourne shell, you can close file descriptors you don't
want open, like 2>&-, which isn't the same as redirecting it
to /dev/null.
1d. More Elaborate Combinations
Maybe you want to pipe stderr to a command and leave stdout alone.
Not too hard an idea, right? You can't do this in the csh as I
mentioned in 1a. In a Bourne shell, you can do things like this:
exec 3>&1; grep yyy xxx 2>&1 1>&3 3>&- | sed s/file/foobar/ 1>&2 3>&-
grep: xxx: No such foobar or directory
Normal output would be unaffected. The closes there were in case
something really cared about all its FDs. We send stderr to sed,
and then put it back out 2.
Consider the pipeline:
A | B | C
You want to know the status of C, well, that's easy: it's in $?, or
$status in csh. But if you want it from A, you're out of luck -- if
you're in the csh, that is. In the Bourne shell, you can get it, although
doing so is a bit tricky. Here's something I had to do where I ran dd's
stderr into a grep -v pipe to get rid of the records in/out noise, but had
to return the dd's exit status, not the grep's:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
The csh has also been known to close all open file descriptors besides
the ones it knows about, making it unsuitable for applications that
intend to inherit open file descriptors.
2. COMMAND ORTHOGONALITY
2a. Built-ins
The csh is a horrid botch with its built-ins. You can't put them
together in many reasonable ways. Even simple little things like this:
% time | echo
which while nonsensical, shouldn't give me this message:
Reset tty pgrp from 9341 to 26678
Others are more fun:
% sleep 1 | while
while: Too few arguments.
[5] 9402
% jobs
[5] 9402 Done sleep |
Some can even hang your shell. Try typing ^Z while you're sourcing
something, or redirecting a source command. Just make sure you have
another window handy. Or try
% history | more
on some systems.
Aliases are not evaluated everywhere you would like them do be:
% alias lu 'ls -u'
% lu
HISTORY News bin fortran lib lyrics misc tex
Mail TEX dehnung hpview logs mbox netlib
% repeat 3 lu
lu: Command not found.
lu: Command not found.
lu: Command not found.
% time lu
lu: Command not found.
2b. Flow control
You can't mix flow-control and commands, like this:
who | while read line; do
echo "gotta $line"
done
You can't combine multiline constructs in a csh using semicolons.
There's no easy way to do this
alias cmd 'if (foo) then bar; else snark; endif'
You can't perform redirections with if statements that are
evaluated solely for their exit status:
if ( { grep vt100 /etc/termcap > /dev/null } ) echo ok
And even pipes don't work:
if ( { grep vt100 /etc/termcap | sed 's/$/###' } ) echo ok
But these work just fine in the Bourne shell:
if grep vt100 /etc/termcap > /dev/null ; then echo ok; fi
if grep vt100 /etc/termcap | sed 's/$/###/' ; then echo ok; fi
Consider the following reasonable construct:
if ( { command1 | command2 } ) then
...
endif
The output of command1 won't go into the input of command2. You will get
the output of both commands on standard output. No error is raised. In
the Bourne shell or its clones, you would say
if command1 | command2 ; then
...
fi
2c. Stupid parsing bugs
Certain reasonable things just don't work, like this:
% kill -1 `cat foo`
`cat foo`: Ambiguous.
But this is ok:
% /bin/kill -1 `cat foo`
If you have a stopped job:
[2] Stopped rlogin globhost
You should be able to kill it with
% kill %?glob
kill: No match
but
% fg %?glob
works.
White space can matter:
if(expr)
may fail on some versions of csh, while
if (expr)
works! Your vendor may have attempted to fix this bug, but odds are good
that their csh still won't be able to handle
if(0) then
if(1) then
echo A: got here
else
echo B: got here
endif
echo We should never execute this statement
endif
3. SIGNALS
In the csh, all you can do with signals is trap SIGINT. In the Bourne
shell, you can trap any signal, or the end-of-program exit. For example,
to blow away a tempfile on any of a variety of signals:
$ trap 'rm -f /usr/adm/tmp/i$$ ;
echo "ERROR: abnormal exit";
exit' 1 2 3 15
$ trap 'rm tmp.$$' 0 # on program exit
4. QUOTING
You can't quote things reasonably in the csh:
set foo = "Bill asked, \"How's tricks?\""
doesn't work. This makes it really hard to construct strings with
mixed quotes in them. In the Bourne shell, this works just fine.
In fact, so does this:
cd /mnt; /usr/ucb/finger -m -s `ls \`u\``
Dollar signs cannot be escaped in double quotes in the csh. Ug.
set foo = "this is a \$dollar quoted and this is $HOME not quoted"
dollar: Undefined variable.
You have to use backslashes for newlines, and it's just darn hard to
get them into strings sometimes.
set foo = "this \
and that";
echo $foo
this and that
echo "$foo"
Unmatched ".
Say what? You don't have these problems in the Bourne shell, where it's
just fine to write things like this:
echo 'This is
some text that contains
several newlines.'
As distributed, quoting history references is a challenge. Consider:
% mail adec23!alberta!pixel.Convex.COM!tchrist
alberta!pixel.Convex.COM!tchri: Event not found.
5. VARIABLE SYNTAX
There's this big difference between global (environment) and local
(shell) variables. In csh, you use a totally different syntax
to set one from the other.
In the Bourne shell, this
VAR=foo cmds args
is the same as
(export VAR; VAR=foo; cmd args)
or csh's
(setenv VAR; cmd args)
You can't use :t, :h, etc on envariables. Watch:
echo Try testing with $SHELL:t
It's really nice to be able to say
${PAGER-more}
or
FOO=${BAR:-${BAZ}}
to be able to run the user's PAGER if set, and more otherwise.
You can't do this in the csh. It takes more verbiage.
You can't get the process number of the last background command from the
csh, something you might like to do if you're starting up several jobs in
the background. In the Bourne shell, the pid of the last command put in
the background is available in $!.
The csh is also flaky about what it does when it imports an
environment variable into a local shell variable, as it does
with HOME, USER, PATH, and TERM. Consider this:
% setenv TERM '`/bin/ls -l / > /dev/tty`'
% csh -f
And watch the fun!
6. EXPRESSION EVALUATION
Consider this statement in the csh:
if ($?MANPAGER) setenv PAGER $MANPAGER
Despite your attempts to only set PAGER when you want
to, the csh aborts:
MANPAGER: Undefined variable.
That's because it parses the whole line anyway AND EVALUATES IT!
You have to write this:
if ($?MANPAGER) then
setenv PAGER $MANPAGER
endif
That's the same problem you have here:
if ($?X && $X == 'foo') echo ok
X: Undefined variable
This forces you to write a couple nested if statements. This is highly
undesirable because it renders short-circuit booleans useless in
situations like these. If the csh were the really C-like, you would
expect to be able to safely employ this kind of logic. Consider the
common C construct:
if (p && p->member)
Undefined variables are not fatal errors in the Bourne shell, so
this issue does not arise there.
While the csh does have built-in expression handling, it's not
what you might think. In fact, it's space sensitive. This is an
error
@ a = 4/2
but this is ok
@ a = 4 / 2
The ad hoc parsing csh employs fouls you up in other places
as well. Consider:
% alias foo 'echo hi' ; foo
foo: Command not found.
% foo
hi
7. ERROR HANDLING
Wouldn't it be nice to know you had an error in your script before
you ran it? That's what the -n flag is for: just check the syntax.
This is especially good to make sure seldom taken segments of code
code are correct. Alas, the csh implementation of this doesn't work.
Consider this statement:
exit (i)
Of course, they really meant
exit (1)
or just
exit 1
Either shell will complain about this. But if you hide this in an if
clause, like so:
#!/bin/csh -fn
if (1) then
exit (i)
endif
The csh tells you there's nothing wrong with this script. The equivalent
construct in the Bourne shell, on the other hand, tells you this:
#!/bin/sh -n
if (1) then
exit (i)
endif
/tmp/x: syntax error at line 3: `(' unexpected
RANDOM BUGS
Here's one:
fg %?string
^Z
kill %?string
No match.
Huh? Here's another
!%s%x%s
Coredump, or garbage.
If you have an alias with backquotes, and use that in backquotes in
another one, you get a coredump.
Try this:
% repeat 3 echo "/vmu*"
/vmu*
/vmunix
/vmunix
What???
Here's another one:
% mkdir tst
% cd tst
% touch '[foo]bar'
% foreach var ( * )
> echo "File named $var"
> end
foreach: No match.
8. SUMMARY
While some vendors have fixed some of the csh's bugs (the tcsh also does
much better here), many have added new ones. Most of its problems can
never be solved because they're not actually bugs per se, but rather the
direct consequences of braindead design decisions. It's inherently flawed.
Do yourself a favor, and if you *have* to write a shell script, do it in the
Bourne shell. It's on every UNIX system out there. However, behavior
can vary.
There are other possibilities.
The Korn shell is the preferred programming shell by many sh addicts,
but it still suffers from inherent problems in the Bourne shell's design,
such as parsing and evaluation horrors. The Korn shell or its
public-domain clones and supersets (like bash) aren't quite so ubiquitous
as sh, so it probably wouldn't be wise to write a sharchive in them that
you post to the net. When 1003.2 becomes a real standard that companies
are forced to adhere to, then we'll be in much better shape. Until
then, we'll be stuck with bug-incompatible versions of the sh lying about.
The Plan 9 shell, rc, is much cleaner in its parsing and evaluation; it is
not widely available, so you'd be significantly sacrificing portability.
No vendor is shipping it yet.
If you don't have to use a shell, but just want an interpreted language,
many other free possibilities present themselves, like Perl, REXX, TCL,
Scheme, or Python. Of these, Perl is probably the most widely available
on UNIX (and many other) systems and certainly comes with the most
extensive UNIX interface. Increasing numbers vendors ship Perl with
their standard systems. (See the comp.lang.perl FAQ for a list.)
If you have a problem that would ordinarily use sed or awk or sh, but it
exceeds their capabilities or must run a little faster, and you don't want
to write the silly thing in C, then Perl may be for you. You can get
at networking functions, binary data, and most of the C library. There
are also translators to turn your sed and awk scripts into Perl scripts,
as well as a symbolic debugger. Tchrist's personal rule of thumb is
that if it's the size that fits in a Makefile, it gets written in the
Bourne shell, but anything bigger gets written in Perl.
See the comp.lang.{perl,rexx,tcl} newsgroups for details about these
languages (including FAQs), or David Muir Sharnoff's comparison of
freely available languages and tools in comp.lang.misc and news.answers.
--
Tom Christiansen Perl Consultant, Gamer, Hiker tch...@mox.perl.com
``Your csh still thinks true is false. Write to your vendor today and tell
them that next year Configure ought to "rm /bin/csh" unless they fix their
blasted shell. :-)'' --Larry Wall in Configure from the perl distribution
T> Archive-name: unix-faq/shell/csh-whynot Version: $Id: csh-faq,v
T> 1.6 94/10/01 09:35:06 tchrist Exp Locker: tchrist $
[crap deleted]
Sounds like you know pretty well about csh. Would you care to learn
to use the precious bandwidth with more constructive manner. Thanks.
--
Junichi Kurokawa
Image and Printing System Products Development Center
Fuji Xerox Co., Ltd.
Explaining to those who might not know it yet that the c-shell is
something to AVOID when you intend to program is not a waste of
bandwith!
And anyway, if you're going to start caring about the bandwith
of a usenet message, go try to censor alt.binaries.pictures.erotica.*,
it wastes a lot more bandwith (yes, totally wastes, since the pics
could be stored at some ftp site instead of being carried all over
the world), and you'll probably find more people agreeing that it's
not "constructive".
--
+----------------------------+---------------------------------------------+
| Roger ESPEL LLIMA | |
| 45, rue d'Ulm | email: roger.es...@ens.fr |
| 75005 PARIS FRANCE | |
+----------------------------+---------------------------------------------+
| Ge mig evig insyn in i drömmarnas land - Först då blir jag lycklig |
| (Änglagård - Kung Bore) |
+--------------------------------------------------------------------------+
Although the bourne shell is probably better to use, it is not perfect, and
I believe that there are some things csh can make easier. For instance:
If I have a text file with multiple records (lines) and each line has multiple
pieces of information separated with spaces or tabs then in csh I can do the
following:
foreach line ("`cat filename`")
.
.
.
end
In this example $line will be set to the entire line for each loop in the for
statement. However, in the bourne shell this would produce one loop with
$line set to the entire file! And if the "'s were removed then each record (line)
would be parsed and $line would be set to the data in between the tabs or spaces
individually, making it very difficult if not impossible to work on complete lines.
Does this mean that I think csh is better for shell programming than sh? No. I
just think that a good shell programmer should know how to use both shells and
admit that neither one is perfect nor completely useless.
---- Kevin
[more crap deleted]
Please just say it straight: This is the csh-haters forum.
Oh well, I'll be a bit more serious: Tom is free to post his biting notes,
and many of us (even I) might agree on most of his accounts, but it should
in no matter be a glorification of "sh", whatever that may be.
~~h
Oh, that's for sure.
:I believe that there are some things csh can make easier. For instance:
Other than ~user and {a,b,c} I disbelieve.
:If I have a text file with multiple records (lines) and each line has multiple
:pieces of information separated with spaces or tabs then in csh I can do the
:following:
:
:foreach line ("`cat filename`")
:In this example $line will be set to the entire line for each loop in the for
:statement. However, in the bourne shell this would produce one loop with
:$line set to the entire file!
That's because you're doing it wrong. You're supposed to use read instead,
which is a shell built-in.
:Does this mean that I think csh is better for shell programming than sh? No. I
:just think that a good shell programmer should know how to use both shells and
:admit that neither one is perfect nor completely useless.
A good shell programmer has to know them in order to maintain brain-dead code written
by those who in ignorance have come before them and selected a bad language for their code.
They should also know when to toss the whole thing out and start over.
And no, I'm not going to admit that the csh is not completely useless for
programming. It's worse than merely useless -- it's downright dangerous
and destructive, and its use should not merely be discouraged, but
banned!
--tom
--
Tom Christiansen Perl Consultant, Gamer, Hiker tch...@mox.perl.com
Some are born to perl, some achieve perl, and some have perl
thrust upon them.
You, k...@cbis.COM (Kevin J. Perkins) write:
>foreach line ("`cat filename`")
> .
> .
> .
>end
>In this example $line will be set to the entire line for each loop in the for
>statement. However, in the bourne shell this would produce one loop with
>$line set to the entire file!
I refute this. Example:
exec <$filename
while read line
do
.
.
.
done
>Does this mean that I think csh is better for shell programming than
>sh? No. I just think that a good shell programmer should know how to
>use both shells and admit that neither one is perfect nor completely
>useless.
set -o egotrip
I call myself a good shell programmer. I know how to use both
shells. I don't use the csh for programming, except when I have
to write .login or .cshrc files. It's nice for interactive use
when you have no access to ksh.
There's only one feature of csh that I sometimes miss in sh, and
that's arithmetic. When I need it I switch to awk or perl.
Even though I've got access to ksh, I try to restrict myself
to the Bourne shell features. And I get the job done in most
cases.
I once found an application written entirely in sh, with
a kind of associative arrays built-in, based on pages of
backquoted references to external commands. No wonder it
was slow as molasses, and buggy as well...
I rewrote and reduced the whole 60page script to two. It just ran.
set +o egotrip
>Sounds like you know pretty well about csh. Would you care to learn
>to use the precious bandwidth with more constructive manner. Thanks.
It never fails. Thanks for continuing to post it, Tom.
--
Fuzzy Fox | "The aardvark is really a curious creature;
f...@netcom.com | If you're an ant, he's likely to eatcher.
<http://mikey. | Although his long nose makes him look rather hideous,
convex.com:8080/> | He's still listed first in the encyclopideous."
Henk> exec <$filename
Henk> while read line
Henk> do
Henk> .
Henk> .
Henk> .
Henk> done
Or even (IMHO) clearer:
<$filename while read line
do
blah
done
Just another Unix hacker (since before there even *was* a csh!),
--
Name: Randal L. Schwartz / Stonehenge Consulting Services (503)777-0095
Keywords: Perl training, UNIX[tm] consulting, video production, skiing, flying
Email: <mer...@stonehenge.com> Snail: (Call) PGP-Key: (finger mer...@ora.com)
Phrase: "Welcome to Portland, Oregon ... home of the California Raisins!"
This is a monthly post which is customarily posted here monthly. Stuff it if
you don't like it.
...
>RANDOM BUGS
...
> !%s%x%s
>
>Coredump, or garbage.
For me, the following dumps core in csh:
!x%s%s
although something like
!x%k%k
seems to work. Why is this? It seems like %s, %d, %x, and possibly others
have a special meaning in csh, which doesn't seem to be documented in the
csh(1) man page.
Does anybody know why?
Top
--
W. Top Changwatchai
w...@cs.utexas.edu
Good point. I have a question though. What if $filename is
not a file but a command [ex: `ls -l | grep Sep` ]. Can you
still do the same thing? (Not trying to promote a war, just
interested in programming techniques).
---- Kevin
Stupid calls to printf().
--tom
--
"...this does not mean that some of us should not want, in a rather
dispassionate sort of way, to put a bullet through csh's head."
Larry Wall in <1992Aug6.2...@netlabs.com>
Yes ... you can do the following:
ls -l | grep Sep | while read line
do
: whatever
done
--
Lloyd Zusman 01234567 <-- The world famous Indent-o-Meter.
l...@panix.com ^ I indent thee.
To get my PGP public key automatically mailed to you, please
send me email with the following string as the subject:
mail-request public-key
>Henk> exec <$filename
>Henk> while read line
>Or even (IMHO) clearer:
> <$filename while read line
> do
> blah
> done
I agree, it looks better and should work according
to the man page, but this is what I get:
bin/testsh: while: not found
bin/testsh: syntax error at line 7: `do' unexpected
exit=2
>Just another Unix hacker (since before there even *was* a csh!)
Henk,
Who only started in '86...
> Randal oversimplifies or we've got a bug in Sun's /bin/sh:
Henk> exec <$filename
Henk> while read line
>> Or even (IMHO) clearer:
>> <$filename while read line
>> do
>> blah
>> done
> I agree, it looks better and should work according
> to the man page, but this is what I get:
> bin/testsh: while: not found
> bin/testsh: syntax error at line 7: `do' unexpected
> exit=2
I also find that the above construct doesn't work. However, this one
always seems to work:
while read line
do
: whatever
done <filename
>I also find that the above construct doesn't work. However, this one
>always seems to work:
> while read line
> do
> : whatever
> done <filename
Agree, but the charm of Randall's solution is that you put
the important stuff at the top, where the reader's attention
goes first.
My original example was actually a specific version of a more
generic approach; if I need to read or write several different
files, I prefer to name them all at the top and refer to them
by fd afterwards. There's a tradeoff in readability, that's
true, but I really hate those scripts with `>>$file' at the
end of every line.
Example:
exec 3<config.file
exec 4>class1
exec 5>class2
exec 6>class3
while read tag field type rest <&3
do
case $something in
...) echo .... >&4
;;
...) echo ... >&5
;;
...) echo ... >&6
esac
done
exec 3<&- 4>&- 5>&- 6>&-
cat class1 class2 class3 > report
Pity to hear that. I'll just continue my 'exec <filename'
habit then.
>One quirk that has bitten bash is that sh allows commands enclosed
>in parens (but not curly braces) to have redirections precede them.
>This makes `(list)' more `special' than other compound commands.
But () and {} have always been different, as the former gives you
a new process, while the latter only groups a couple of commands
into their own environment. I think this is the entire purpose
of having two different constructs...
In sh programming there are two things that you always need
to be aware of:
- Does redirection spawn a subprocess?
- Is this change in the environment transient
or permanent?
And () and {} deal with these two questions explicitly.
The parens garantuee that you have a subprocess, and it
is always possible to redirect i/o for a subprocess.
Any changes to variables/environment are lost at the end of
the () construct.
The braces only perform grouping of commands, and because
they don't allow redirection, one can safely assume that
any changes within the {} construct are permanent.
But Randal, this is not the same. At least on SunOS 4.1.3 it
doesn't even work.
$ cat bad.sh
#!/bin/sh
flag=0
<aa while read line
do
flag=1
done
echo $flag
$ ./bad.sh
./bad.sh: while: not found
./bad.sh: syntax error at line 5: `do' unexpected
It can be made to work if it is changed to this
$ cat half_bad.sh
#!/bin/sh
flag=0
while read line
do
flag=1
done <aa
echo $flag
but the while is run in a subshell in most Bourne shells, so any
variable set inside the loop is lost after the done. The exec
means that the while loop is run in the shell itself and any variable
assignments survive outside the while loop.
$ cat good.sh
#!/bin/sh
flag=0
exec <aa
while read line
do
flag=1
done
echo $flag
--
Goran Larsson Phone: +46 13 155535 FAX: +46 13 160533
Approve AB +46 589 12810 +46 589 16901
h...@lorelei.approve.se ...!uunet!mail.swip.net!lorelei!hoh
solidaritet = gruppegoism
I agree that the SunOS sh manual page implies that the above should
work, but it never has. The Posix.2 grammar makes it explicit that
these `compound commands' may not be preceded by redirections.
One quirk that has bitten bash is that sh allows commands enclosed
in parens (but not curly braces) to have redirections precede them.
This makes `(list)' more `special' than other compound commands.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
Chet Ramey, Case Western Reserve University Internet: ch...@po.CWRU.Edu
>Yes ... you can do the following:
> ls -l | grep Sep | while read line
> do
> : whatever
> done
Just personal preference, but I like to code this as:
ls -l | grep Sep |
while read line
do
: whatever
done
But that's just a style issue.
You have to take care, though, as the while will be executed
in a subshell, and you cannot rely on any results being preserved
after completion of the pipeline. If you want to do something
with the results, you'd have to use
ls -l | grep Sep |
(
while read line
do
: whatever
done
: more
)
HENK> exec <$filename
HENK> while read line
In reply to Randall, it seems the Cc: feature of the (old) nn
I run kills the actual post, I have only one defense:
bin/testsh:
<$filename while read line
do
echo $line
done
bin/testsh: while: not found
bin/testsh: syntax error at line 7: `do' unexpected
exit=2
For which my syntax is a work-around.
The man page suggests otherwise, but this problem
happens on both solaris 2.3 and sunos 4.1.2...
Thanks for reminding me of a bug.
>I also find that the above construct doesn't work. However, this one
>always seems to work:
> while read line
> do
> : whatever
> done <filename
There is a little trap here. The bourne shell will put the while
statement in a subshell. Try:
while read line
do
x=not
done < /etc/passwd
echo $x broken
(This is of course also true for "command | while ...")
"exec < /etc/passwd ; while ..." does the job.
Michael.
---------------------------------------------------------------
Michael Schroeder mlsc...@faui43.informatik.uni-erlangen.de
main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}
> You can fault Tom for his biting sarcasm about csh, but he's not
> glorifing sh -- only saying that csh is a braindead language in
> comparison to a competent (no, not glorious) language like sh.
Oh no? Look at this great statement:
TC> White space can matter:
TC>
TC> if(expr)
TC>
TC> may fail on some versions of csh, while
TC>
TC> if (expr)
TC>
TC> works!
Looks like sh has got one up on csh here doesn't it? But wait! Let's
try this exact same thing in sh:
if[ -d /tmp ]; then
echo hello
fi
>> `then' unexpected
Oh. So how about these variations? (Common lines omitted).
if [-d /tmp ]; then >> [-d:Not found
if [ -d /tmp]; then >> ] missing
And most amazingly of all:
if [ -d /tmp ]; then
# echo hello
fi
>> `fi' unexpected !!!!!
(And I've tried these on SunOS 4.1, Irix 4.05, Irix5.2, ConvexOS 10.1
and AIX 3.2.5 just in case you're wondering...)
Interestingly this is the only part of the document that has changed
since this time last year. TC has realised that most vendors have now
fixed this so he has added:
TC> Your vendor may have attempted to fix this bug, but odds are good
TC> that their csh still won't be able to handle
TC>
(more complex example that defeats most vendors' csh deleted)
And this for something sh hasn't fixed at all!! Which strangely he
doesn't mention...
It's economical with the truth. Only anti-csh points are mentioned.
There is no discussion of the bugs or points you need to worry about
using sh. tcsh gets a very short mention even though it fixes most of
the bugs mentioned (including all the ones sh fails on above *and*
Tom's counter example). I look forward to the next version of TC's
document pointing out the superiority of tcsh over sh in this area.
Cleary the document is aimed at people using csh as their login
shell. Tom's solution? Learn sh!! And for what? Just to write ten line
sh scripts! Because anything longer both Tom and I write in perl.
If you want to *help* these people, Tom, tell them to change their
login shell. Tell them to get their sys admin to install tcsh. Or, if
they want to be brave, tell them to learn a new shell with command
line editing, programmable completion, history searching, the things
that make their everyday lives easier.
You see, I don't believe this document was really written primarily to
enpower people, to point out the pros and cons so that they can make
an informed choice of what's best in their situation.
Call me cynical....
BTW, if you are using csh as your login shell, ask your sys admin to
install tcsh from tesla.ee.cornell.edu. If you're using sh, see if
your system has ksh or ask your sysadmin to get bash or zsh. It's
these things that will actually improve the use of the computer.
Or try both tcsh and zsh and see which you prefer.
And if you are writing any significant shell 'programs' learn perl
or one of its competitors.
John
The truth, the whole truth and nothing but the truth.
>TC> White space can matter:
>TC>
>TC> if(expr)
>TC>
>TC> may fail on some versions of csh, while
>TC>
>TC> if (expr)
>TC>
>TC> works!
>Looks like sh has got one up on csh here doesn't it? But wait! Let's
>try this exact same thing in sh:
>if[ -d /tmp ]; then
> echo hello
>fi
But that's just how sh works. if[ is an unknown command. The square
brackets are *not* part of the syntax of the Bourne shell.
The "[" command is just that: a command.
You should mentally translate:
if[ ... ]
to
iftest ...
and then sh's complaints make a lot of sense.
Csh's problem is big, run the following through csh and explain
why it echos 'bar not foo' and not 'not foo' (when bar and foo aren't set).
(Tcsh has this bug fixes: the problem is that csh uses a different "parser"
for not taken branches of an if statement, sh's syntax is regular.
if ( $?foo ) then
if( $?bar) then
echo bar and foo
else
echo not bar and foo
endif
else
echo not foo
endif
>Oh. So how about these variations? (Common lines omitted).
They make all perfect sense.
>And most amazingly of all:
>if [ -d /tmp ]; then
># echo hello
>fi
>>> `fi' unexpected !!!!!
Also makes sense, except that I don't like teh fact that empty
stament lists aren't allowed in many cases in sh.
>Interestingly this is the only part of the document that has changed
>since this time last year. TC has realised that most vendors have now
>fixed this so he has added:
>And this for something sh hasn't fixed at all!! Which strangely he
>doesn't mention...
It isn't broken in sh. Why should sh care about that the person
who implemented the test command later added the deature that
you can call test as "[" provided argv[argc - 1] == "]" because
he felt it looked nice in shell scripts?
The Bourne shell does not have the bugs you believe you detected, which
takes away the foundation of the rest of your argument.
>You see, I don't believe this document was really written primarily to
>enpower people, to point out the pros and cons so that they can make
>an informed choice of what's best in their situation.
It is to warn people who have a csh-like login shell and know a little
*csh programming needed to maintain ~/.cshrc and ~/.login *not*
to use *csh for programming. And he's right. As soon as you start
programming in csh you'll run into all the problems, the first one
being: "how do I write a message on stderr?".
Casper
> [ ... stuff deleted to save bandwidth ... ]
> It's economical with the truth. Only anti-csh points are mentioned.
> There is no discussion of the bugs or points you need to worry about
> using sh. tcsh gets a very short mention even though it fixes most of
> the bugs mentioned (including all the ones sh fails on above *and*
> Tom's counter example). I look forward to the next version of TC's
> document pointing out the superiority of tcsh over sh in this area.
A minor point: does tcsh allow redirection of stderr only (i.e.,
without it being combined with stdout and without having to go through
the contortions one has to go through to get this behavior in csh)?
This was the main reason I switched away from csh several years ago.
> BTW, if you are using csh as your login shell, ask your sys admin to
> install tcsh from tesla.ee.cornell.edu. If you're using sh, see if
> your system has ksh or ask your sysadmin to get bash or zsh. It's
> these things that will actually improve the use of the computer.
> Or try both tcsh and zsh and see which you prefer.
I agree!
> l...@panix.com (Lloyd Zusman) writes:
>> I also find that the above construct doesn't work. However, this one
>> always seems to work:
>> while read line
>> do
>> : whatever
>> done <filename
> Agree, but the charm of Randall's solution is that you put
> the important stuff at the top, where the reader's attention
> goes first.
Well, unless your shell supports Randall's solution (and many versions
of the Bourne Shell don't), you will be forced to use something much
less charming. :)
> My original example was actually a specific version of a more
> generic approach; if I need to read or write several different
> files, I prefer to name them all at the top and refer to them
> by fd afterwards. There's a tradeoff in readability, that's
> true, but I really hate those scripts with `>>$file' at the
> end of every line.
> Example:
> exec 3<config.file
> exec 4>class1
> exec 5>class2
> exec 6>class3
>
> [ ... rest of example deleted to save space ... ]
I agree with you and I recommend your 'exec ...' approach. It is just
as charming as the other approach, and it actually works in all
versions of the Bourne Shell I have used. :)
Even funnier; the results you give apply when executed as a shell
script:
$ cat > blbl.csh
#!/bin/csh
if ( $?foo ) then
if( $?bar) then
echo bar and foo
else
echo not bar and foo
endif
else
echo not foo
endif
$ chmod 755 blbl.csh
$ ./blbl.csh
not bar and foo
... BUT
if i try to get csh to execute this at the command line, it does the
following:
$ csh
drakkar% if ( $?foo ) then
? if( $?bar) then
? echo bar and foo
? else
drakkar% drakkar%
i.e. keeps asking me for lines until that "else", then considers that
the structure is done (with 2 if's and no endif, i wonder how), then
gives me 2 prompts instead of one, for the same price!
And how about this bug? (i don't know if this one is known...)
$ cat > hello.c
main() { puts("this is just another csh bug"); }
$ gcc hello.c -o hello
$ PATH=hello:$PATH
$ csh
drakkar% ``
this is just another csh bug
drakkar% exit
BUT
$ PATH=/users/93/maths/espel/tmp/hello:$PATH
$ csh
drakkar% ``
/users/93/maths/espel/bin/: Permission denied.
(and my ~/bin directory exists, and is executable and readable and there
are no permission problems anywhere with it)
while with sh, bash and ksh evaluating `` doesn't give any results,
and with zsh it gives
zsh: parse error in command substitution
in all cases
--
+----------------------------+---------------------------------------------+
| Roger ESPEL LLIMA | |
| 45, rue d'Ulm | email: roger.es...@ens.fr |
| 75005 PARIS FRANCE | |
+----------------------------+---------------------------------------------+
| Ge mig evig insyn in i drömmarnas land - Först då blir jag lycklig |
| (Änglagård - Kung Bore) |
+--------------------------------------------------------------------------+
: Although the bourne shell is probably better to use, it is not perfect, and
: I believe that there are some things csh can make easier. For instance:
: If I have a text file with multiple records (lines) and each line has multiple
: pieces of information separated with spaces or tabs then in csh I can do the
: following:
: foreach line ("`cat filename`")
: .
: .
: .
: end
#!/bin/sh
exec 0<filename # take stdin from filename
while read line
do
.
.
.
done
and you avoid the overhead of cat and a pipe
: In this example $line will be set to the entire line for each loop in the for
: statement. However, in the bourne shell this would produce one loop with
: $line set to the entire file! And if the "'s were removed then each record (line)
: would be parsed and $line would be set to the data in between the tabs or spaces
: individually, making it very difficult if not impossible to work on complete lines.
: Does this mean that I think csh is better for shell programming than sh? No. I
: just think that a good shell programmer should know how to use both shells and
: admit that neither one is perfect nor completely useless.
: ---- Kevin
--
Dan Mercer ClearSystems, Inc
Reply To: dame...@mmm.com "The Mad Pedant"
======================================================================
All opinions expressed are my own and do not reflect the opinions of
my employer or my employer's clients, in particular 3M Company.
All advice or software offered or presented is provided As Is with no
warranty either expressed or implied. Follow at your own risk.
Objects in the mirror are closer than they appear.
In article <36jvrb$6...@csnews.cs.Colorado.EDU>,
Tom Christiansen <tch...@mox.perl.com> wrote:
:Archive-name: unix-faq/shell/csh-whynot
:Version: $Id: csh-faq,v 1.6 94/10/01 09:35:06 tchrist Exp Locker: tchrist $
:
:The following periodic article answers in excruciating detail
:the frequently asked question "Why shouldn't I program in csh?".
:It is available for anon FTP from convex.com in /pub/csh.whynot .
[...]
:
:Consider this statement in the csh:
:
:
: if ($?MANPAGER) setenv PAGER $MANPAGER
:
:
:Despite your attempts to only set PAGER when you want
:to, the csh aborts:
:
: MANPAGER: Undefined variable.
:
:That's because it parses the whole line anyway AND EVALUATES IT!
:You have to write this:
:
: if ($?MANPAGER) then
: setenv PAGER $MANPAGER
: endif
:
:That's the same problem you have here:
:
: if ($?X && $X == 'foo') echo ok
: X: Undefined variable
:
:This forces you to write a couple nested if statements. This is highly
:undesirable because it renders short-circuit booleans useless in
:situations like these. If the csh were the really C-like, you would
:expect to be able to safely employ this kind of logic. Consider the
:common C construct:
:
: if (p && p->member)
:
:Undefined variables are not fatal errors in the Bourne shell, so
:this issue does not arise there.
WHAT THE HELL KIND OF A STUPID ARGUMENT IS THAT?
He goes on and on withthis rant about csh not having short-circuit
evaluation, then refuses to discuss its presence in sh, just informing us
that sh allows you to foolishly reference variables that don't exist, so
"we don't have that problem here." I'd say non-existent variables not
causing an error is a bigger problem than not having short-circuit
operators anyway. Thanks for the tip buddy, I'll never use sh again (as if
I ever have)
--
Alan |GE d? H s++:-- g+++ p? !au a-- v--- C+++ UB++ P-- L>+++ 3>+++ E--- N* K-
Curry|W+>! M-- !V -po+ Y+ t+(+++) 5++ j- R- G? tv++ b- D++>+++ B--- e+ u h f?
r--(---) y? n---- "You can't save everybody, just try not to be living next
door to them when they go off." --Dennis Miller
--
Alan |GE d? H s++:-- g+++ p? !au a-- v--- C+++ UB++ P-- L>+++ 3>+++ E--- N* K-
Curry|W+>! M-- !V -po+ Y+ t+(+++) 5++ j- R- G? tv++ b- D++>+++ B--- e+ u h f?
r--(---) y? n---- "You can't save everybody, just try not to be living next
door to them when they go off." --Dennis Miller
People occasionally do that when they have something constructive to offer --
and always seem to do so when they do not.
:WHAT THE HELL KIND OF A STUPID ARGUMENT IS THAT?
:He goes on and on withthis rant about csh not having short-circuit
Speaking of rants....
:I'd say non-existent variables not
:causing an error is a bigger problem than not having short-circuit
:operators anyway. Thanks for the tip buddy, I'll never use sh again (as if
:I ever have)
I'm not particularly enamoured of shell programming, as you might understand
had you been reading the net for longer than the last few weeks or so.
To denigrate the csh is not always to glorify the bourne shell.
Your pleasing tone was, as always, duly appreciated.
:Alan |GE d? H s++:-- g+++ p? !au a-- v--- C+++ UB++ P-- L>+++ 3>+++ E--- N* K-
^^^
Well, that explains a lot. Children these days. Sheesh! Brash, rude,
and hopelessly lacking in background and context. If, young man, you go
back and check the last dozen or more years or so of my USENET postings,
you'll have a better chance of knowing where I'm coming from. Ignorance
is curable, but being that uncouth merits a boot to the head or a
Killfile.
for i in `cat foo`; do
:
done
problem is to set IFS. For details: RTFM sh(1).
--
Thomas Esser email: t...@informatik.uni-hannover.de
Universitaet Hannover, Institut fuer Informatik (Systemadministration)
: Henk> exec <$filename
: Henk> while read line
: Henk> do
: Henk> .
: Henk> .
: Henk> .
: Henk> done
: Or even (IMHO) clearer:
: <$filename while read line
: do
: blah
: done
Under HP-UX 9.01:
$ filename=a
$ <$filename while read line
do
while: not found
$ syntax error: `do' unexpected
$ echo "$line"
$ done
syntax error: `done' unexpected
: Just another Unix hacker (since before there even *was* a csh!),
: --
: Name: Randal L. Schwartz / Stonehenge Consulting Services (503)777-0095
: Keywords: Perl training, UNIX[tm] consulting, video production, skiing, flying
: Email: <mer...@stonehenge.com> Snail: (Call) PGP-Key: (finger mer...@ora.com)
: Phrase: "Welcome to Portland, Oregon ... home of the California Raisins!"
--
> T> Archive-name: unix-faq/shell/csh-whynot Version: $Id: csh-faq,v
> T> 1.6 94/10/01 09:35:06 tchrist Exp Locker: tchrist $
> [crap deleted]
>Sounds like you know pretty well about csh. Would you care to learn
>to use the precious bandwidth with more constructive manner. Thanks.
Bother, its the monthly flame war again :-(
Csh program considered harmful is a vital document which has saved many a
soul from the demon that is csh. So vital that its archived as an FAQ because
it answers the FAQ "how do I do X in csh". Its not wasting your bandwidth,
since it saves bandwidth on pointless csh questions.
Maybe you should read it ??
--
Brian Blackmore.
So I have been off for six months now... and I'm really, really, glad to see
things are as they ever have been.
You may be happy to hear that since this corp is sold on csh, I have really
been having the worst time making things work. A normal login takes at least
10 seconds and accesses no less than six *.csh files. Basically, I wrote a
little script which cleans the output from the env command and makes a sort
of . file which I call .envfil. Dotting that makes really sand makes a dot
file which I call .envfil.
_poohbear
After I spent many hours figuring out this out,
I never wrote another csh script... (I use bash...)
if ($?MANPATH) unsetenv MANPATH # to be safe
if ($?PATH) unsetenv PATH
if ($?INFOPATH) unsetenv INFOPATH
# look for and add directories if they exist for toolkits
foreach i ( $stuff )
if ( -d $i/bin ) then
if ($?PATH) then
setenv PATH "$PATH"":$i/bin"
else
setenv PATH $i/bin
endif
endif
# else if works but else alone doesn't seem to. Why?
if (-d $i/man) then
if ($?MANPATH) then
setenv MANPATH "$MANPATH"":$i/man"
else
setenv MANPATH $i/man
endif
endif
if (-d $i/info) then
if ($?INFOPATH) then
setenv INFOPATH "$INFOPATH"":$i/info"
else
setenv INFOPATH $i/info
endif
endif
end
and stuff is off the form:
set stuff = ( ~ \
/usr/gnu \
/usr/local \
/usr/local-in-some-other-place \
/usr/local-in-/this/palce
)
--
marty
lei...@sdsp.mc.xerox.com
Member of the League for Programming Freedom
C++ is to C as lung cancer is to lung.
: T> Archive-name: unix-faq/shell/csh-whynot Version: $Id: csh-faq,v
: T> 1.6 94/10/01 09:35:06 tchrist Exp Locker: tchrist $
: [crap deleted]
: Sounds like you know pretty well about csh. Would you care to learn
: to use the precious bandwidth with more constructive manner. Thanks.
: --
: Junichi Kurokawa
: Image and Printing System Products Development Center
: Fuji Xerox Co., Ltd.
Its interesting people who write csh scripts are concerned about
bandwidth ;-)
Tom's advice is so accurate -- don't use the csh...
Much of the time, the real answer to a programming question is
"why are you doing it this way?"
which the programmer often doesn't want to hear.
Which goes back to the fundamental thing -- don't use the csh...
Bandwidth is wasted posting questions about csh obscurities...
--
marty
lei...@sdsp.mc.xerox.com
Member of the League for Programming Freedom
I don't make many mistakes, but when I make one, its a beaut
Fiorello LaGuardia
> I'm not particularly enamoured of shell programming, as you might understand
> had you been reading the net for longer than the last few weeks or so.
> ... If, young man, you go
> back and check the last dozen or more years or so of my USENET postings,
> you'll have a better chance of knowing where I'm coming from.
I see... So to answer your posts, Tom, you first have to find a site
archiving all of your USENET postings, then spend the time to read them
all, and then, if you still don't consider you as a Net God, you may
use the reply command of your news reader?
I don't care how ignorant you feel the replying person is; he's doing
what most of us are doing: reacting to the post he's just read on the
net. If that posting doesn't give all the background information you
feel he should know about, that's the fault of the original poster (you),
not of the reader.
You could have answered this person politely and pointing out where he
lacks knowledge; instead, you give him the message "I've been on the
net much longer than you, lad, so you should learn to shut up before
you've aquired the same amount of information and wisdom as I have".
Do you think you've convinced him not to use the C shell any longer?
Even though I agree with you that there are better scripting languages
than csh, I wouldn't write it off completely. I have myself used csh as
a scripting language for several years without any big problems. The
reason for this is that I've always used (t)csh as my interactive shell,
and I don't want to learn two different shell syntaxes. I thus started
writing scripts in csh, and now it would take too much time to learn
another shell and rewrite my existing scripts.
Before you abruptly tell someone to stay away from csh, which I have seen
you doing, you should try to find out why this person is interested in
csh help. If he's interested in learning UNIX shell programming from
scratch, or in teaching shell programming to others, I agree with you
that csh isn't a good choice. Otherwise, one should be more careful about
the advice given. I can understand people getting annoyed when asking a
question about how to do something in csh and getting the answer "don't
use csh." It might be true, but it sure isn't very helpful or considerate.
Over time, I've learned and accepted the defiencies of csh and found
ways to overcome some of them. Just for the fun of it, and to prove it
can be done, I have for instance written a csh script for extracting
and uu-decoding binary files from multi-part postings in the 'binaries'
news groups. It does a better job than UNPOST and UUSHRED written in C,
but is of course much slower. It's absurd to write such a program in
csh, but it shows that it _is_ possible to do 'serious' work in csh.
It may have been easier in Perl or sh, but that's not the point.
--
_______ __ __ _ _ ,------- Michagon -------.
/ _____|\ | \/ (_)___| |__ ___ __ _ ___ _ __ | (Thomas Michanek) |
/ <|___ \|| . . | / __) '. `-_ / _` / _ \ '. | | Trumslagaregatan 118 |
|\_____|> / |_|`'|_|_\___)_||_(_,_\__, \___/_||_| |S-58346 Linkoping SWEDEN|
\|______/ |_____________________|___/_________| |+46 13 273727(voice/fax)|
D o c u m e n t a t i o n - I n f o r m a t i o n `--- x...@telelogic.se ---'
> Csh program considered harmful is a vital document which has saved many a
> soul from the demon that is csh.
With a statement like that, no doubt this subject is referred to as a
religious war... After having programmed succesfully using the C shell
for some time, I know for sure this is going to far. Or perhaps I have
a twisted mind that is soon to be overtaken by the devil?
> So vital that its archived as an FAQ because
> it answers the FAQ "how do I do X in csh".
Oh no, it doesn't!!! It tries to answer the question "why shouldn't I
program using csh" which is a quite a different matter. However, it
is often posted or referred to when someone asks how to do something
in csh.
Before one abruptly tells someone to stay away from csh, one should try
to find out why this person is interested in csh help. If he's interested
in learning UNIX shell programming from scratch, or in teaching shell
programming to others, I agree with you that csh isn't a good choice.
Otherwise, one should be more careful about the advice given. I can
understand people getting annoyed when asking a question about how to do
something in csh and getting the answer "don't use csh." It might be true,
but it sure isn't very helpful or considerate.
> Its not wasting your bandwidth,
> since it saves bandwidth on pointless csh questions.
C shell questions are only pointless for those who don't use it regularly.
You may have very good reasons for staying away from csh yourself, but
that doesn't make questions about it pointless.
Even though I agree with you that there are better scripting languages
than csh, I wouldn't write it off completely. I have myself used csh as
a scripting language for several big tasks without any serious problems.
Over time, I've learned and accepted the defiencies of csh and found
ways to overcome some of them.
I'll always be happy to answer people who have questions about csh.
If you think they need a pointer to something better, give a such a
pointer politely to them. Slashing Tom's "FAQ" in their face is a much
worse behaviour than programming in csh in the first place!!!
kjp> Although the bourne shell is probably better to use, it is not
kjp> perfect, and I believe that there are some things csh can make
kjp> easier. For instance:
kjp> If I have a text file with multiple records (lines) and each
kjp> line has multiple pieces of information separated with spaces
kjp> or tabs then in csh I can do the following:
kjp> foreach line ("`cat filename`")
kjp> .
kjp> .
kjp> .
kjp> end
kjp> In this example $line will be set to the entire line for each
kjp> loop in the for statement. However, in the bourne shell this
kjp> would produce one loop with $line set to the entire file! And
In the bourne shell do
cat filename | while read line
do
.
.
done
It is a lack of csh that you cannot use redirection very well with the
built in control structures.
--
Peter Mutsaers | AT Computing bv, P.O. Box 1428,
p...@atcmp.nl | 6501 BK Nijmegen, The Netherlands
tel. work: +31 (0)80 527248 |
tel. home: +31 (0)3405 71093 | "... En..., doet ie het al?"
: > Randal oversimplifies or we've got a bug in Sun's /bin/sh:
: Henk> exec <$filename
: Henk> while read line
: >> Or even (IMHO) clearer:
: >> <$filename while read line
: >> do
: >> blah
: >> done
: > I agree, it looks better and should work according
: > to the man page, but this is what I get:
: > bin/testsh: while: not found
: > bin/testsh: syntax error at line 7: `do' unexpected
: > exit=2
: I also find that the above construct doesn't work. However, this one
: always seems to work:
: while read line
: do
:
: : whatever
:
: done <filename
But has the drawback that it generates a sub-shell (a fork without an exec)
Thus, any variables set within the loop, or any directory changes
within the loop are lost when the loop completes.
: --
: Lloyd Zusman 01234567 <-- The world famous Indent-o-Meter.
: l...@panix.com ^ I indent thee.
: To get my PGP public key automatically mailed to you, please
: send me email with the following string as the subject:
: mail-request public-key
--
This is also available on the WWW in the directory
http://www.cit.gu.edu.au/~anthony/info/shell/
_____ _ _____ _ _
/ ____| | | / ____| | | |
| | ___| |__ | (___ | |_ __ _ _ __| |_ _ _ _ __
| | / __| '_ \ \___ \| __/ _` | '__| __| | | | '_ \
| |____\__ \ | | | ____) | || (_| | | | |_| |_| | |_) |
\_____|___/_| |_| |_____/ \__\__,_|_| \__|\__,_| .__/
_____ | |
/ ____| |_|
| (___ _ _ _ __ ___ _ __ ___ ___ _ __ _ _
\___ \| | | | '_ ` _ \| '_ ` _ \ / _ \ '__| | | |
____) | |_| | | | | | | | | | | | __/ | | |_| |
|_____/ \__,_|_| |_| |_|_| |_| |_|\___|_| \__, |
__/ |
|___/
This document contains a summized guide to the startup process for the
csh and tcsh unix shell. In this guide you will find:-
INDEX 1) Sections executed on startup under various conditions
INDEX 2) What should/could be perform in each startup section
INDEX 3) T/csh setup requiring no ``.login'' file.
INDEX 4) A solution to X Window environment initialization problem
INDEX 5) Csh Startup modularization
INDEX 6) Small tricks, aliases and other bit 'n' pieces
INDEX 7) Disclamer: Csh Script Programming Considered Harmful
-- Anthony Thyssen (ant...@cit.gu.edu.au)
-- Paul Davey (p...@x.co.uk)
------------------------------------------------------------------------------
INDEX 1) Sections executed on startup under various conditions
Assuming that the .cshrc file is divided into two sections depending on
if the `prompt' was defined by the shell program.
* Interactive (prompt defined -- normal user session)
* Non-Interactive (prompt undefined -- script or rsh initialization)
EG:
#echo "Executing .cshrc script"
#----- non-interactive shell -----
if ( ! $?prompt ) then # test if non-interactive (script or remote)
...
...
exit 0
endif
#------- interactive shell --------
...
...
NOTE: The non-interactive section should be very small and fast, providing
the minimal amount of setup required to work. The only thing which must be
provided is a minimal `path', particularly containing the normal unix
binary directories and the X Windows directory.
EG:
set path = (/usr/ucb /usr/bin /usr/local/bin /usr/bin/X11)
This create three posible sections that can be executed on startup, (two
in .cshrc, and one in .login) and you may want to include a fourth section
with .logout (exit csh script)
Here are all the situations that I can find and the parts in the above
scheme which are are executed for that situation :-
csh script with a -f option no sections performed at all
csh script without -f option non-interactive .cshrc script only
remote command (rsh) non-interactive .cshrc script only
vi shell escapes / file manager non-interactive .cshrc script only
sub-shell (t/csh or plain xterm) interactive .cshrc only
full login or xterm -ls interactive .cshrc and .login
in that order (and .logout on exit).
-- Anthony Thyssen (ant...@cit.gu.edu.au)
------------------------------------------------------------------------------
INDEX 2) What should/could be perform in each startup section
non-interactive .cshrc (scripts, remote and shell escaped commands)
* set important (must have) environment variables if we are csh
(tcsh does "HOST" and "HOSTTYPE" automatically for you)
* default path so the X11 commands can be found without a full path,
as well as for t/csh scripts without the (-f) flag
* small number of aliases for use in rsh, the Sun Open Window File
Manager user menu or as vi shell escapes.
* set umask (for remote commands or they run with umask 0)
interactive .cshrc (All Csh and Tcsh related stuff should be here)
* set complete interactive path for normal usage. This could be in
.login but is here because the non-interactive test normally does not
exist. It also places both path definitions in the same file for
easier handling.
* csh/tcsh settings:- prompts, filec, cdpath, periodic(tcsh).
* full alias list for user's usage. I actually place this in a
.cshaliases file which I source.
* the cd-prompt hack for csh IE :-
alias cwdcmd 'set prompt="$cwd:t> "' alias cd 'chdir \!* && cwdcmd'
full session startup -- .login (stuff to be set up once only)
See also INDEX 3 for incorperating this into .cshrc
* complete environment variable initialization
* miscellanous commands : umask, stty, mesg
* determine where we are logged in from (say for printer selection)
* start window system if nessary
* specialized terminal type setup. For example:-
+ dialin, network, or unknowen
terminal type correction for pc's, macs, and home computers (amiga)
+ xterm
determine DISPLAY and terminal size on remote machines
set the xterminal title (IE: to the current host name)
* checks for mail, news and other login notifications
* check on breakin / illegal account access/usage
* opening messages
exiting full session -- .logout (script called on logout)
Remember .logout is called only if the shell exits normally:
This can lead to problems if your shell core dumps and then you have
to deal with a ``You are already logged in'' message 'cos .logout
didn't decrement a login count.
* cleanup of account
* closing messages
* session summeries
NOTE: You do not need to do all the above. I myself do most of them except
for a couple which is not needed in my own setups.
If you have anything to add to this list please let me know.
-- Anthony Thyssen (ant...@cit.gu.edu.au)
------------------------------------------------------------------------------
INDEX 3) T/csh setup requiring no ``.login'' file.
I recently ceased using .login for anything. It's handy for setting the
environment once but since it is read after .cshrc you can not use its
variables in aliases etc. I now detect a login (or rsh job) by the fact
that the environment (actually just the environment variable ENVSET) is
not set.
EG: in .cshrc script (immediately after non-interactive checks)
# IS THE ENVIRONMENT SET?
if ( $?ENVSET == 0 ) setenv ENVSET -1 # insure ENVSET is defined
if ( $ENVSET != 1) then # is the environment set
# ---- normal login section ----
# do environment setup and terminal checks here
...
setenv ENVSET 1
endif # ENVSET != 1
-- Paul Davey (p...@x.co.uk)
------------------------------------------------------------------------------
INDEX 4) A solution to X Window environment initialization problem
For X it is convenient to have several clients (especially a window
manager) started at login and of course this can be done from scripts
such as .xsession run from xdm.
However clients started from .xsession do not inherit the users
(carefully tailored) environment from .cshrc/.login. One way around this
is to make .xsession a csh script which sources .cshrc and/or .login but
this is not particularly fast, reliable or portable.
My solution is to make .xsession set a environment flag (XLOGIN) to 1
and to start one xterm (with shell) only. Within .cshrc a new section
starts initial clients when XLOGIN is 1 after the environment has been
initialized. It then sets XLOGIN to 0 to prevent this happening again if
the file is reread.
This allows the environment to be set in one file without having to
source .cshrc from a .xsession written in csh (can't source csh from sh).
Of course if you are logging in and running startx or xinit from the
command line this approach is not needed as the X session inherits the
environment from the login shell; This method will however cope with that
case as well (my .xinitrc is a link to .xsession).
EG for .xsession script
#!/bin/sh
# .xsession file
HOST="@`hostname`"
xrdb $HOME/.Xdefaults
XLOGIN=1
export XLOGIN
exec xterm -ls -geometry 80x24+0-0 -T "LOGIN$HOST" -n "LOGIN$HOST"
AND in the .cshrc script (after the environment setup (see above) )
if ( $?XLOGIN ) then
unsetenv XLOGIN
# set a local csh variable for this critical xterm (started .xsession)
set ignoreeof
# ---- start other X clients ----
# Should really check xconsole exists (and works) before this bit
# wait for xconsole to fork before continuing
xconsole -daemon -geom 700x100-0-0
csh -f << EOF >& /dev/console
set verbose
twm &
xterm -name xterm-$HOST -geometry 80x45+0+0 &
xclock -g 100x100-0+0 &
xsetroot -fg red -bg black -mod 2 2 &
EOF
endif # XLOGIN
-- Paul Davey (p...@x.co.uk)
NOTE:
I myself do not like this method, instead I opt'ed for sourcing a bourne
shell script with the appropiate minimal environment required in the
.xsession file. This requires a bourne shell environment setup (sourced
from .xsession) as well as a csh environment setup (from .login). It
works for me.
--- Anthony Thyssen
------------------------------------------------------------------------------
INDEX 5) Csh Startup modularization
You may find it useful to actually split sections of your .cshrc into
separate files. These can be read in with the source command which reads
and evaluates a file in the current shell, ie without forking a subshell.
(It is the equivalent of the ``.'' command in sh).
Breaking the .cshrc file into smaller files to be sourced, has certain
advantages.
* Reading of the .cshrc programming stucture is easier
* All the aliases and environment variables are defined in the one place
For example:
i) Define your aliases in ~/.cshaliases
ii) In .cshrc give the command ``source ~/.cshaliases'' in the
interactive section defined above.
Some canidates for modurizations are
.cshaliases defines all your csh aliases
.cshenv environment variable definitions (sourced from .login)
.cshlogin a .login replacment to call from .cshrc ? (see INDEX 3)
.cshXstartup X window startup clients script (see INDEX 4)
.cshprompt script to set the csh prompt according to current directory
The above are only suggestions, the file names used for the sourced csh
scripts can be anything you like, or even stored in a .csh sub-directory.
Any sourcing of an external file will slow down evaluation, but only
very slighly.
-- Paul Davey & Anthony Thyssen
------------------------------------------------------------------------------
INDEX 6) Small tricks, aliases and other bit 'n' pieces
This is a list of small ``tricks'' that can be incorperated into your
own .cshrc/.login startup files.
i) Show only new MOTD (messages of the the day) on login
if (-f /etc/motd ) then
cmp -s /etc/motd ~/.hushlogin
if ($status) tee ~/.hushlogin < /etc/motd
endif
ii) Changing the prompt to reflect the current directory
alias setprompt 'set prompt = "`pwd` > "'
alias cd 'chdir \!* && setprompt'
alias pushd 'pushd \!* && setprompt'
alias popd 'popd \!* && setprompt'
setprompt
iii) Searching for a particular process (given as argument)
alias pf 'ps auxgw | cut -c1-15,36-99 |\\
awk "/\!:1/ && ! /(awk)/ || NR==1"'
iv) Multiline prompt
alias setprompt 'set prompt="\\
${hostname:h}:${cwd}\\
\! % "'
v) Log remote (rsh) out non-interactive commands executed in this account.
add something like the following to your .cshrc (non-interactive part)
if ( ! $?prompt ) then
# Record the
set column = "`ps ww1 | head -1`" # figure out column from ps header
set column = `expr "$column" : '\(.*\)COMMAND' : '.*' + 1`
ps ww$$ | tail -1 | cut -c${column}- >> ~/command.log
exit
endif
-- miscellanous sources
------------------------------------------------------------------------------
INDEX 7) Disclamer: Csh Script Programming Considered Harmful
There are plenty of reasons not to use csh for script writing (see Csh
Programming Considered Harmful [anon ftp from convex.com /pub/csh.whynot])
This file is an attempt to explain how to make it easier and more
convenient to use it interactively. It does NOT provide a guide to using
csh as a general script writing language, and the authors recommend that
it not be used for that purpose.
But why use csh interactively?
The aliases and history list alone make it worthwhile, extra features
such as file completion, tilde expansion, and job control make even more
useful. The tcsh command line editing and other interactive enhancements
make it one of the best interactive shells around.
There are arguably `better' shells avaliable that can be used, but I
have found many of them lacking in some important aspect or, generally not
installed on most systems. A delivered vanilla machine however, is almost
certain to have csh. A .cshrc and .login setup can then be easily copied
and is available immediately.
Faced with the choice between plain sh and bad old csh I'll take csh any
day.
-- Paul Davey (p...@x.co.uk)
-- Anthony Thyssen (ant...@cit.gu.edu.au)
------------------------------------------------------------------------------
Anthony Thyssen ( System Programmer ) http://www.cit.gu.edu.au/~anthony/
-------------------------------------------------------------------------------
All these theories, diverse as they are, have two things in common.
They explain all the observed facts and they are complete and utterly
WRONG. --- Terry Pratchet - "The Light Fantastic"
-------------------------------------------------------------------------------
try this in Bourne shell (or any derivative, e.g. ksh, bash):
while read line ; do
munge $line
done < filename
$line is the next line of filename each time through the loop. (Try piping into
a loop in csh!). Note that this is also far more efficient (no subshell, no cat).
Whereof one cannot speak, thereof one should be silent. :-)
cheers
andrew
While you and Brian are ROTFL, I've come to the conclusion that even
people who are very experienced and knowledgeable in UNIX and programming,
and who've been on the net for years, still don't know how to help others
and point them in the right direction in a polite and respectful way.
At least in my experience, before you offer someone a solution to a
problem, you should try to understand that persons situation.
You are welcome to continue posting your FAQ and telling people with
csh questions to stay away from the csh abyss, as long as you give me
and others on the net the right to actually give them short-term help.
Neither my brain, nor my computer system, is dead despite the fact I'm
using csh whenever I feel it's an adequate tool for the job.
--
_______ __ __ _ _ ,------- Michagon -------.
/ _____|\ | \/ (_)___| |__ ___ __ _ ___ _ __ | (Thomas Michanek) |
/ <|___ \|| . . | / __) '. `-_ / _` / _ \ '. | | Trumslagaregatan 118 |
|\_____|> / |_|`'|_|_\___)_||_(_,_\__, \___/_||_| | 583 46 Linkoping |
\|______/ |_____________________|___/_________| | 013-27 37 27 (tel/fax) |
D o k u m e n t a t i o n - I n f o r m a t i o n `--- x...@telelogic.se ---'
No! Not the evil bash! Ugh.
> if ($?MANPATH) unsetenv MANPATH # to be safe
> if ($?PATH) unsetenv PATH
> if ($?INFOPATH) unsetenv INFOPATH
Why are you checking if they exist? If you want them empty, just unsetenv
them - csh won't complain.
> # look for and add directories if they exist for toolkits
> foreach i ( $stuff )
> if ( -d $i/bin ) then
> if ($?PATH) then
> setenv PATH "$PATH"":$i/bin"
> else
> setenv PATH $i/bin
> endif
> endif
Again - you just unset PATH, so why are you checking if PATH exists? Even
if it doesn't exist, you can still do the $PATH:$i/bin thing. And why
all those quotes? Just do:
setenv PATH $PATH':'$i/bin
The same comments hold for a while...
> end
>
>and stuff is off the form:
>
>set stuff = ( ~ \
> /usr/gnu \
> /usr/local \
> /usr/local-in-some-other-place \
> /usr/local-in-/this/palce
> )
Interesting idea, but you did a lot of things that you didn't need to do -
no wonder you don't like csh... You really did things the hard way.
--
fn info guess {if {~ $guess 'James Ojaste'} {echo Right!} {~ $guess es-lover} {
echo Yup!} {~ $guess descartes.uwaterloo.ca} {echo Uh-huh!} {echo Bzzzt!}}
PLM> In the bourne shell do
PLM> cat filename | while read line
PLM> do
PLM> .
PLM> .
PLM> done
Aha. The winner of this week's "useless use of cat" award.
Hint: nearly any time you have just *one* argument to cat, you
*probably* don't need the cat.
The correct answer is posted at least two or three times already in
this thread. (Yes, mine was one of the wrong answers... sigh.)
Just another would-be shell programmer (if it weren't for Perl :-),
--
Tom Christiansen Perl Consultant, Gamer, Hiker tch...@mox.perl.com
Emacs is a fine programming language, but I still prefer perl. -me
Na.. we all know what the best .login file is....
if (-x /bin/bash) then
exec /bin/bash
endif
echo "PANIC WE ARE IN KSH"
(Sorry couldn't resist that)
--
Brian Blackmore.
"In most bourne shells" ... that says enough.
Perhaps we should have "Sh Programming Considered Harmful"? I certainly
like "Csh Programming Considered Harmful" a lot. It demonstrates lots
of things about csh which are just hard to believe that they are true
when you start using it. I don't use csh except when being forced to,
but I always thought I should read the entire manual carefully to
finally find out how to redirect stderr. Hard to imagine it simply is
not possible. Unless such problems just bite you, the posting is even
funny.
sh has such quirks as well, although not as my as far as I know.
Nevertheless, the above trouble with while on some systems being
executed in a subshell when used with redirection is quite unexpected.
So, sh haters: Make a collection of such things. People then can
compare the bugs, and decide which set they like less.
Michael
--
Twiggs and root are a wonderful tree (tm) Twiggs & root 1992 :-)
>try this in Bourne shell (or any derivative, e.g. ksh, bash):
>while read line ; do munge $line; done < filename
>$line is the next line of filename each time through
>the loop. (Try piping into a loop in csh!). Note that
>this is also far more efficient (no subshell, no cat).
Hi Andrew,
We had a whole thread dedicated to this: the indirection
itself causes the shell to spawn of a separate process for
the loop.
Use "exec <filename; while read line; do stuff $line; done" instead.
Be that as it may, it has very little to do with what I was talking
about. The difference is in the grammar, not the behavior of the
constructs. There are a number of `compound commands' listed as such
in the sh man page, but only `()' allows redirections to precede it.
This is what makes `()' a special case, not that it is guaranteed to
create a subshell.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
Chet Ramey, Case Western Reserve University Internet: ch...@po.CWRU.Edu
>I don't care how ignorant you feel the replying person is; he's doing
>what most of us are doing: reacting to the post he's just read on the
>net. If that posting doesn't give all the background information you
>feel he should know about, that's the fault of the original poster (you),
>not of the reader.
Have you bothered to read the stupid and insulting post Tom was
responding to? No, I didn't think so. Have you bothered to read Tom's
original post, informative and comprehensive (Csh Programming Considered
Harmful)? No, I didn't think so. You just mouth off, without having
the faintest understanding of what's going on.
t.
He's back!
Granted csh has some nasty bugs, especially on SVR4 systems, but there
is one thing which I do a lot where I think the csh handling of file
descriptors (specifically redirection) is superior.
Can Bourne shell match the simple elegance of
(whatever) |& $PAGER
where I want both the stdout and the stderr to be processed by the
pager to prevent loss of any error messages that may arise? I suppose
it's probably possible to get this effect in Bourne shell, somehow, but
the method is not obvious and I doubt it's as simple.
The problem, of course, is the combination of the pipe with the
left-to-right Bourne parsing of redirection: if I say
(whatever) 2>&1 | $PAGER
I suppose it will put stderr on the former stdout (probably the tty)
and direct only stdout into the pipe. If I try
(whatever) | 2>&1 $PAGER
or
(whatever) | $PAGER 2>&1
I'd expect it to be $PAGER's stderr that gets redirected somewhere.
That works just fine for me.
--tom
PH> Can Bourne shell match the simple elegance of
PH> (whatever) |& $PAGER
PH> The problem, of course, is the combination of the pipe with
PH> the left-to-right Bourne parsing of redirection: if I say
PH> (whatever) 2>&1 | $PAGER
PH> I suppose it will put stderr on the former stdout
Actually, these two constructs are equivalent. I agree however that
|&, along with >&, is more elegant as easier to type. Which is why
I'm so happy with the Z-Shell. Zsh combines the sanity of sh with all
the fun toys from every other shell you ever heard of!
--
=[ cooper ]=
>PLM> In the bourne shell do
>PLM> cat filename | while read line
>PLM> do
>PLM> .
>PLM> .
>PLM> done
>Aha. The winner of this week's "useless use of cat" award.
>Hint: nearly any time you have just *one* argument to cat, you
>*probably* don't need the cat.
>The correct answer is posted at least two or three times already in
>this thread. (Yes, mine was one of the wrong answers... sigh.)
And for the exception that proves the rule, Linux users might like to
try to remove the cat in the following.......
cat /proc/ksyms|less
Mind you that still doesn't mean that 99% of cats with one argument are
useless, this just happens to be a member of the 1%.
--
Brian Blackmore.
I wondered about that, too. Is there *any* case where
cat file | prog
and
prog < file
are not equivalent?
--
Paul DuBois
dub...@primate.wisc.edu
> I wondered about that, too. Is there *any* case where
>
> cat file | prog
> and
> prog < file
>
> are not equivalent?
Here's the closest thing I could come up with ...
rsh anotherhost cat file | prog
... and ...
rsh anotherhost prog < file
... do not do the same thing.
And the following is a third case that is also different from the
other two ...
rsh anotherhost "prog < file"
These all do the same thing only if 'prog' and 'file' are identical on
your host and 'anotherhost'.
> But that's just how sh works. if[ is an unknown command. The square
> brackets are *not* part of the syntax of the Bourne shell.
Let me just make sure I've got this right. The fact that some vendors'
csh forces you to put a space in "if(expr)" (and the vast majority
don't) is a point against csh. The fact that all vendors' sh forces
you to put spaces in "if[expr]" is "just how sh works". And the fact
that:
if [ -d /tmp ]; then
# echo hello
fi
doesn't work in sh but
if ( -d /tmp )
# echo hello
endif
works fine in csh "Also makes sense" and is not in any way a point in
which csh behaves better than sh.
By definition one can answer any criticism of anything by saying
"That's just the way xyz works".
Looks like the csh programmers have got a pretty good answer to all
the points in CPCH eh?
It's not a BUG, it's a FEATURE!
John (who never uses csh BTW)
>In article <36u3te$r...@mail.fwi.uva.nl> cas...@fwi.uva.nl (Casper
>H.S. Dik) writes:
>> But that's just how sh works. if[ is an unknown command. The square
>> brackets are *not* part of the syntax of the Bourne shell.
>Let me just make sure I've got this right. The fact that some vendors'
>csh forces you to put a space in "if(expr)" (and the vast majority
>don't) is a point against csh. The fact that all vendors' sh forces
>you to put spaces in "if[expr]" is "just how sh works". And the fact
>that:
You still haven't got the point. The many C-shells will interpret
"if( ..." different from "if (" depending on whether the if is in a branch
of an if that's being taken or an untaken branch. The C-shell uses two
*different* parsers.
>By definition one can answer any criticism of anything by saying
>"That's just the way xyz works".
The point is *not* whether the C-shell accepts "if(" or not.
What does the following echo in *your* C-shell?
unset foo bar
if ( $?foo ) then
if( $?bar) then >& /dev/null
echo bar and foo
else
echo not bar and foo
endif
else
echo not foo
endif
Obviously, the *right* answer is not foo.
You'll also notice that the redirection at the end of the then line
is perfectly acceptable to the C-shell at the top level (it throws
away all output of the if-expression).
The point is that the C-shell doesn't *parse* it's input,
it adhoculates it.
Casper
: He's back!
: Granted csh has some nasty bugs, especially on SVR4 systems, but there
: is one thing which I do a lot where I think the csh handling of file
: descriptors (specifically redirection) is superior.
: Can Bourne shell match the simple elegance of
: (whatever) |& $PAGER
You answer this yourself:
(whatever) 2>&1 | $PAGER
which is exactly 3 characaters less "elegant" than csh. The pipeline is
set up before stderr is redirected, so stderr is dup'ed to the pipe.
Now, don't you feel foolish.
Maybe Tom should change his article to:
"Why programming in csh causes brain damage"
Csh: Just Say No!
: where I want both the stdout and the stderr to be processed by the
: pager to prevent loss of any error messages that may arise? I suppose
: it's probably possible to get this effect in Bourne shell, somehow, but
: the method is not obvious and I doubt it's as simple.
: The problem, of course, is the combination of the pipe with the
: left-to-right Bourne parsing of redirection: if I say
: (whatever) 2>&1 | $PAGER
: I suppose it will put stderr on the former stdout (probably the tty)
: and direct only stdout into the pipe. If I try
: (whatever) | 2>&1 $PAGER
: or
: (whatever) | $PAGER 2>&1
: I'd expect it to be $PAGER's stderr that gets redirected somewhere.
--
> You still haven't got the point. The many C-shells will interpret
> "if( ..." different from "if (" depending on whether the if is in a branch
> of an if that's being taken or an untaken branch. The C-shell uses two
> *different* parsers.
> The point is *not* whether the C-shell accepts "if(" or not.
Well it's good of you to tell me what the point of my article was
Caspar. However, the copy *I* kept made no mention of whether csh was
in any way better or worse than sh. What I asked was: "Why does CPCH
castigate csh for being space sensitive in this way without mentioning
that sh is also space sensitive?" Your answer - that with csh it's a
bug (which it clearly is) whereas with sh it's a feature doesn't
strike me as being too useful to Joe User. At least a bug can be
fixed. Few sensible people are very interested in the relative merits
of csh and sh as programming languages. If they want to program they
use perl, etc. What is useful to people is someone honestly trying to
list the pros and cons of each, not mere advocacy. If you want to
do that become a lawyer.
John
If the only tool you have is a hammer everything looks like a nail.
Those who are ignorant of history are doomed to use sh.
I guess I had better put a ':-)' after that last one for you guys huh?
> In article <37blk3$h...@mail.fwi.uva.nl> cas...@fwi.uva.nl (Casper H.S. Dik) writes:
>
>> You still haven't got the point. The many C-shells will interpret
>> "if( ..." different from "if (" depending on whether the if is in a branch
>> of an if that's being taken or an untaken branch. The C-shell uses two
>> *different* parsers.
>
>> The point is *not* whether the C-shell accepts "if(" or not.
>
>Well it's good of you to tell me what the point of my article was
>Caspar. However, the copy *I* kept made no mention of whether csh was
>in any way better or worse than sh. What I asked was: "Why does CPCH
>castigate csh for being space sensitive in this way without mentioning
>that sh is also space sensitive?" Your answer - that with csh it's a
>bug (which it clearly is) whereas with sh it's a feature doesn't
>strike me as being too useful to Joe User. At least a bug can be
>fixed. Few sensible people are very interested in the relative merits
>of csh and sh as programming languages. If they want to program they
>use perl, etc. What is useful to people is someone honestly trying to
>list the pros and cons of each, not mere advocacy. If you want to
>do that become a lawyer.
I think the point is that in csh the "(" and ")" are part of the language,
whereas in sh the "[" is not strictly speaking part of the language, but
just an alias for the test command. (Which happens to be built into most
bourne shells for efficiency reasons). Therefore there is a good reason
why you need a space after the if and before the command in bourne shell
whereas there is no good reason to require a space between the "if" and "("
in csh.
Yes.
The Bourne shell's "if" command is brilliant elegance. It executes any
command and branches on the return value. The form of the command is
if list
where list is a command pipeline.
The [ command is a stupid kludge, that masquerades as syntax for the
benefit of people who are not interested in this elegance. But it's
not an integral part of the Bourne shell. Even where there's a "["
built in, there's also a "test" command that does the same thing without
the syntax fraud.
Donn Cave, do...@cac.washington.edu
[etc]
This brings up a question.
In csh, if I have a link to somewhere and I 'cd' to it, a 'pwd' reports
my location as if I had followed that link step by step.
In ksh, it would report my location as something like
"/home/mcrafts/mylink" without telling me where I -really- am.
In the past I've always had to do something like 'csh -c /bin/pwd' to get
my true directory, but is there a way to actually get that in ksh?
Mark
--
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Mark Crafts Melbourne FL
cra...@iia.org
William Hall
>In csh, if I have a link to somewhere and I 'cd' to it, a 'pwd' reports
>my location as if I had followed that link step by step.
>In ksh, it would report my location as something like
>"/home/mcrafts/mylink" without telling me where I -really- am.
>
>In the past I've always had to do something like 'csh -c /bin/pwd' to get
>my true directory, but is there a way to actually get that in ksh?
The undocumented `pwd -P'.
The points he raises are indeed legitimate criticisms of a particular
implementation of the C shell. But the implicit extension from there
to a general indictment of the whole C shell language is unwarranted.
To me, this is a little like looking at K&R's very first C
compiler ca. 1970 and trying to draw conclusions about where the
C language is going in the 90's.
Bill Joy's original C shell -- the one all of you working on a UNIX
system are faced with -- is indeed a terrible implementation. I've
seen the code and can't believe Bill had ever seen the inside of a
compiler class when he wrote it. All the parsing is completely
ad hoc. To execute a loop, his C shell seeks on the input to run
back to the top to reparse and continue execution. Quoted strings are
marked internally by setting the high bit in each of the characters.
It goes on. The code is junk. Joy clearly had no clue at the time of
how any of these problems are classically solved. The fact that his
C shell worked at all is a stark testament to the brute force of
the man's intelligence and drive. Lacking the formal training, he
simply steam-rollered over the implementation problems.
Still, Bill Joy did make some important contributions to shell
design that I think even Tom will acknowledge. The overall style
is, without question, more modern. All the reversed keywords --
the esac's and fi's, etc. -- in the Bourne and Korn shells look,
to my taste, pretty damn dated. Reading an sh or ksh script reminds
me of CACM article ca. 1970. Why anyone would want to fool with
that kind of junk in the 90's is beyond me. The C shell constructs
reflect a lot more of what we know today about what a language
should look like.
Joy also introduced two other seminal innovations: an expression
grammar built right into the shell and, second, a history mechanism
for recalling and editing previous commands.
But the problem we keep coming back to is that Joy's implementation
just wasn't very good. And while there have been some hacks done
to it (e.g., tcsh to add filename completion, etc.), by and large
nothing has fundamentally changed in that code base in more than
a decade since Joy wrote it.
That's a long, long time in the computer world.
Today, Joy's C shell is not the only C shell in the world any more
than UNIX is the only small multi-tasking operating system in the
world. Myself, I am the author of Hamilton C shell for OS/2
and Windows NT. This is a completely from-scratch recreation of the
C shell for these newer operating systems. Not one line of code has been
ported from anywhere else. Here are some of the basic architectural
and feature differences:
1. The overall design is organized much more like a classical compiler
with a top-down recursive descent parser which generates an
intermediate code which is then lightly optimized (constant
propagation, etc.) and passed to a separate execution unit.
The benefits are two-fold. First, you get a much more predictable,
easy to use language. The language becomes free-format and easier
to type. It avoids all the nuttiness in Joy's C shell where, e.g.,
you think you know how to do A and also how to do B, but when you
try coupling A to B, it doesn't work. (An example Tom gives is
piping who into a while statement; that doesn't work in Joy's C
shell but certainly does work in mine.) It also avoids all the
crazy evaluation errors, e.g., where conditional expressions
aren't really conditionally evaluated or where constructs (e.g.,
quoting) can't be nested properly, etc. In my C shell,
things work the way you'd expect.
Second, you get much better performance. The actual details of
the intermediate code are that the internal representation is
sort of LISP-like in the sense you have lots of little things
pointing to other little things, representing the parse tree.
The idea was to balance the competing demands that it be fast
to generate during the parse, fast to evaluate during execution
and fast to tear down when it was no longer needed (e.g., when
a statement is no longer reachable). On equivalent hardware,
my C shell is, quite simply, faster than any of the UNIX shells.
2. The expression grammar has been dramatically improved both with
the addition of support for floating point and, more important
from an ease-of-use standpoint, by the relaxation of the
keying rules.
Bill Joy's C shell required that you type spaces around all the
operators and $'s in front of any variable names. The only thing
worse I can imagine would be a shell that DIDN'T let you type spaces
around the operators! :-) In any event, the result is that most
users experienced the frustration of typing expressions that were
perfectly readable, done the way their fingers knew how to in C, but
which the C shell would refuse. So everyone wasted a lot of time
retyping things.
In my C shell, wherever the context is an expression, the parser shifts
gears to examine the input the way any other high-level language
compiler might do it. In its normal mode where it's just collecting
a command + some arguments, the parser collects the text word-at-
time, looking for wildcards, etc. But when the context is an
expression, it begins tokenizing. So where a*b would be a single
word with a wildcard normally, it means the usual multiplication
of variables a and b inside an expression. Spacing is totally
arbitrary as is the use of $'s in front of variable names. If you
want to type things the way you would in Joy's C shell, that still
works, but you don't have to. The result is more of what we might
call "do what I mean."
3. All the "missing" pieces have been filled in. Both built-in and
user procedures have added. There's even a printf! Arguments to
a procedure can be named whatever you like, the same as you would
expect in any other decent high-level language. Block-structured
local variables have added. There's a genuine numeric for loop
as in "for i = 1 to 10 do ... end". (What kind of moron designs
a HLL and leaves that out? :-)
Procedures, by the way, couple nicely with the whole style of
compiling to an internal form. It becomes trivial to write
what I call self-loading procedures: the first time you reference
them, you pay for the compilation as it's loaded from a script.
After that, any new invocations transparently call the pre-compiled
form already sitting in memory. For free, you suddenly get
a 3x or 4x boost in performance in many cases.
4. Command line and other limits are just plain gone. The only
exceptions are those just simply outside my control, namely those
imposed by the operating system (e.g., in child process creation,
OS/2 imposes a limit of 64K and NT imposes a limit of 32K bytes
of command line data).
I know I'm not the only one who's been frustrated with every UNIX
shell in existence. Sure, they support very long command lines,
but every time you really need it, it's not long enough. In my
C shell, everything is totally dynamic, allocated as needed and
limited only by virtual memory. Want to iterate with a foreach
over a couple megabyte-long list of filenames? No problem. Try
that with any other shell.
5. This shell is highly multi-threaded. E.g., if you type
a | b | c
each stage of the pipeline is passed off to a new, dynamically-
spawned thread for evaluation. If any given stage refers to an
internal command, that will be run just within that thread. If
it's an external command, any path searching and process creation
activities are overlapped with similar activities in the other
threads. Blocking events tend to be more effectively overlapped
rather than serialized. Coupled with the roughly order-of-magnitude
lower costs of spawning threads vs. processes, the result is
drammatically better responsiveness. It's just plain faster.
6. Although all the usual !!-style history mechanisms are still
there, this shell offers full-screen command line editing with
cut 'n paste using the cursor keys. As you insert characters
into command line, the whole rest of the screen is instantly
updated, keeping right up with keystrokes. None of that idiotic
stuff you see with some shells where you get only a little one-
line window into the command line buffer or where, as you type,
you can _watch_ the cursor run back 'n forth across the display
-- even _after_ you finish typing! -- updating the screen.
Command line editing includes features for easily recalling
whole sequences of commands, for filename completion, and
of course for command completion, recalling commands from
history based on content.
7. A lot of creature comforts have been added and more regularity
introduced into the language. E.g., Joy's C shell used slightly
(but maddenly!) different syntax for the alias, set and setenv
commands even though each was really doing pretty much the
same thing, i.e., associating a string of words with a name
in the appropriate dictionary. In my C shell, you can type
any one of these commands any way you like and it just works.
Another, more exciting improvement was made to the wildcarding
with the addition of what I call "indefinite directories". The
elipsis, "...", is a new construct meaning "zero or more
directory levels -- whatever it takes to make the rest of the
pattern match." So, e.g., to grep for "foo" in all the .c or
.h files in this or any subdirectory of /source, you need only
type
grep foo /source/.../*.[ch]
Think of that the next time you're struggling with find! (Is
there anyone who _ever_ gets find to do what they want the
first time?) Matter of fact, some things you can easily do with
"..." defy any reasonable implementation with find. Consider,
for example:
grep foo /source/.../{x,y}/.../*.[ch]
By the way, I've typed my examples using /'s in the filename,
UNIX-style even though both OS/2 and NT use \; my C shell lets
you do whatever you prefer. I don't get religious on that kind of
stuff. I just take the simpler view that the customer is
always right. :-)
Yet another example of the general improvement in ease-of-use
is in the diagnostics. Instead of the usual cryptic complaints
you see from the UNIX shells, I actually give meaningful messages
including stack traces. What a concept! :-)
Here's an example, where I've got a divide-by-zero exception
inside a procedure called from within a command substitution:
5% proc x(y)
6? return 1/y
7? end
8% echo `x 0`
csh(line 6): Integer divide by zero.
> in x( "0" ) defined at line 5
< called from line 8
> in `x 0`
< called from line 8
csh: Requested run-time substitution failed.
Turning to Tom's specific complaints about Bill Joy's C shell, it
becomes clear that, by and large, he's talking about problems that
really exist only in that implementation.
1. File descriptors. Tom devotes a lot of space to complaining about
the C shell's lack of support for the 2>x notation for redirection.
Some of this is warranted. When I began the design of my own C
shell, I did give some consideration to this construct. It didn't
make it into the final cut (there are always lots more good ideas
waiting to be done than time to do them) but may happen someday.
But let me call your attention to the language problem this
construct glosses over. On the one hand, you'd like the language
to be free-format, so that spacing doesn't matter. But then you
have to reconcile
echo I want door number 2 > answer
Is the "2" an argument or a file descriptor? Sh and Ksh offer
an answer, namely that it's a descriptor only if the > _immediately_
follows. Is that the right thing to do? I honestly don't know
though I will say that compromising the free format does make
me shudder a little. My own aesthetic preference as a language
designer would have been, I think, for an unambiguous grammar,
e.g., parenthesizing the "2" out of the context of the rest
of the command:
(foo) 2 > errors
Another problem glossed over is the parochial view of file
descriptors as small integers, e.g., when Tom talks about the
joys of redirecting descriptors 4 and 5 and so on. Not all
operating systems work that way even though they may still
agree on the idea of having designated handles for stdin,
stdout and stderr. NT is a good example: file handles are
intended to be opaque types, meaning you're not supposed
to attach any meaning to the particular binary value. For
all practical purposes, the actual handle values are just
random numbers. Certainly, NT does have a notion of stdin,
stdout and stderr so that even if the actual handles values
are different, we can still refer to them symbolically as
0, 1 and 2. But the extension beyond that to 3, 4 and 5
just does not work.
Other points Tom raises are truly just implementation issues
or "features" of questionable merit. For example, in my C shell,
$< (or the alias, $getline), does properly read stdin (even if
stdin has been redirected).
Regarding the Bourne shell "feature" of closing a file descriptor
-- he gives the example of 2>&- to close stderr -- I'm still
wondering why I want to do that.
In another example, Tom describes the problem of the following
pipeline, where you'd like to capture the status coming back from A:
A | B | C
and gives an example of how he'd do this in Bourne shell:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
Frankly, I'm not sure WHAT this does (Tom, are you sure this isn't
APL? :-) but I can tell you how you'd grab the status of A in my
C shell:
(A; @ x = $status) | B | C
exit $x
You tell me: which you rather read (or have to write)?
2. Command orthogonality.
2a. Built-ins. All of this stuff is fixed. Each of
the examples Tom gives do work properly in my C shell:
% time | echo
csh: '|' cannot be the beginning of a statement.
(My C shell defines the time command as taking an argument which
must be non-null statement or control structure.)
% sleep 1 | while
csh: Couldn't find a '(' to introduce the test in a 'while'
statement.
Certainly, there are no problems typing the end-of-file character
into the shell nor do simple things like
% history | more
cause any hangs.
Aliases are properly expanded everywhere. For example,
% alias x echo hello
% repeat 3 x
hello
hello
hello
%time x
hello
0:00:00.06
2b. Flow control. Again, all this is fixed. You certainly can
mix flow-control and i/o redirection or piping. For example:
% ls
a b c
% ls | while (! eofgetline)
% echo $upper(getline)
% end
A B C
Using semicolons to put a multi-line construct onto a single
line is also no problem:
% alias D (if (-D ^!^*) echo dir; else echo not dir; end)
% D a
not dir
% D \tmp
dir
(In this example, I had the escape character set to the ^,
NT or OS/2-style and used the \ as the directory slash; this
is configurable.)
It certainly is possible to do redirections in an if statement,
solely for the exit status:
% if ({grep thread threads.h >nul}) echo found
found
% if ({grep foozork threads.h >nul}) then echo found
? else echo not found; end
not found
and certainly, too, pipes do work:
% if ({grep threads threads.h | wc}) echo ok
69 413 3358
ok
2c. Stupid parsing bugs. Well, again, these are just plain fixed.
Some of Tom's examples in this section are a little too OS-dependent
to easily transcribe on OS/2 or NT for demostration, but in each
case, the underlying bug in Joy's C shell just does not exist in
mine.
For example, certainly white space does not make a difference, so
these two lines are equivalent:
if(expr) ...
if (expr) ...
and the following properly produces no output:
if(0) then
if(1) then
echo A: got here
else
echo B: got here
endif
echo We should never execute this statement
endif
3. Signals. This turns out to be an OS-dependency. UNIX offers
a greater variety of signal types than do either OS/2 or NT.
If there had been more than just the simple Ctrl-C or Ctrl-Break
interrupt under OS/2 or NT, they'd have been reflected in the
language as I'd implemented it. On the other hand, I do some
things that, to the best of my knowledge, are not handled well
by any of the UNIX shell, such as the ability to push/pop the
interrupt handler.
4. Again, all this works as it should. For example,
% set foo = "Bill asked, ^"How's tricks?^""
% echo $foo
Bill asked, "How's tricks?"
% alias trythis (echo `echo `echo hello world``)
% trythis
hello world
% set foo = "this is a ^$dollar quoted and this is $HOME not quoted"
% echo $foo
this is a $dollar quoted and this is j:\doug not quoted
% set foo = "this^
and that"
% echo foo
this
and that
Escaping history references are no problem:
% mail adec23^!alberta^!pixel.Convex.COM^!tchrist
Alternately, if you _really_ don't like the history mechanism
getting in the way, you can simple turn it off, in which case
the !'s have no special meaning.
5. Variable syntax. Again, all totally fixed. Environment and
shell variables can be manipulated with the same syntax. All
the : editing operators do work on environment and all other
variables. E.g., $SHELL:t does properly produce csh.exe.
The id of the last child process you started is available as
$child. And so on.
6. Expression evaluation. Again, all totally fixed. For example,
variable substitution is properly done only when the statement
is evaluated, not before, so Tom's examples following do work
as expected:
if ($?MANPAGER) setenv PAGER $MANPAGER
if ($?X && $X == 'foo') echo ok
Also, as outlined, spaces do not matter, so both of the following
produce exactly the same result:
@ a = 4/2
@ a = 4 / 2
The one example Tom presents that arguably does not work as
expected (at first glance) in my C shell is the following:
% alias foo echo hi; foo
csh: Couldn't find an executable file named 'foo'.
But this is the definition of the alias mechanism, not a
parsing bug as Tom claims. The C shell parses the entire
line before executing any part of it. The assumption is
that if you have a parsing bug anywhere on the line, you'd
first like to correct it. This is the same assumption
made in sh and ksh, where, for example, you'd see the
following result of a syntax error:
$ ls; for
syntax error: got End of line, expecting argument
But alias expansion is done in the parser while setting
of aliases is a run-time time function. What this means
is that the alias foo is not yet known at the time the
line is parsed because the assignment has yet been
executed. An alternative would be to use a procedure,
which does work as expected, since the procedure call
is fully a run-time operation:
% proc foo() echo hi; end; foo
hi
7. Error handling. Again, all this is fixed. Also, as mentioned,
the situation is much better than with any of the UNIX shells
in terms of stack tracing, etc.
Random bugs. Again, all this craziness is fixed. For example:
% repeat 3 echo "/vmu*"
/vmu*
/vmu*
/vmu*
% mkdir tst
% cd tst
% touch '[foo]bar'
% foreach var ( * )
> echo "File named $var"
> end
File named [foo]bar
Putting this altogether, it becomes clear by the existence proof
that not C shells have to be, as Tom puts it, "bad for your health".
Joy's implementation was flawed. But that's yesterday's news.
The question isn't what the language used to be but where it is
today. And with a modern implementation, the answer is the C shell
provides superior perforance and a more readable and expressive
style.
I have quite a number of customers happily building scripts that
run to thousands and thousands of lines of lines of code. They're
undertaking projects that would have been unthinkable or at least
unreasonable with any of the UNIX shells. For example, Martin
O'Riordan, well-known in the C++ community for his work on the
Glockenspeil and Microsoft C++ compilers, built a system of
over 7,000 lines of C shell scripts to handle his nightly
regression testing. This is a fellow who, I think we can all
agree, does know something about language design and certainly
is not unaware of his other choices.
A good C shell that addresses the complaints Tom voices is not
only possible, it exists today. Now, I admit, if you're still
stuck on UNIX, you're still stuck with Joy's version; I've had
some requests from my OS/2 and NT customers that I port my C shell
to UNIX but I haven't yet seen (and make no promises there will
ever be) a sufficient business case for a small company like
mine.
But if you are indeed working on OS/2 or Windows NT, I'd be happy
to let you see for yourself what can be done with the C shell.
I have literature and free demo versions I'm happy to mail out.
Just send me email, telling me your postal mailing address and
your preference for the OS/2 vs. the NT version and, if it's
for NT, whether it's for Intel, MIPS, DEC Alpha or IBM PowerPC.
Regards,
Doug Hamilton KD1UJ hami...@bix.com Ph 508-440-8307 FAX 508-440-8308
Hamilton Laboratories, 21 Shadow Oak Drive, Sudbury, MA 01776-3165, USA
> Today, Joy's C shell is not the only C shell in the world any more
> than UNIX is the only small multi-tasking operating system in the
> world. Myself, I am the author of Hamilton C shell for OS/2
> and Windows NT. This is a completely from-scratch recreation of the
> C shell for these newer operating systems. Not one line of code has been
> ported from anywhere else. Here are some of the basic architectural
> and feature differences:
>
> [ ... list of features deleted to save space ... ]
This looks really good! Congratulations!
When will this be available to run under Unix? Is this freeware, or
proprietary?
> 1. File descriptors. Tom devotes a lot of space to complaining about
> the C shell's lack of support for the 2>x notation for redirection.
> Some of this is warranted. When I began the design of my own C
> shell, I did give some consideration to this construct. It didn't
> make it into the final cut (there are always lots more good ideas
> waiting to be done than time to do them) but may happen someday.
I would like to vote for '2>x', or if you don't like that specific
notation, SOME way to redirect stderr without stdout. I use this
functionality frequently, and the absence of the ability to easily do
this is what finally drove me away from 'csh' for good. With all the
really nice features of your rewritten C shell, I would still end up
not using it much if I couldn't redirect stderr alone ... and this
would be unfortunate, because I am quite impressed with what you have
done.
Keep up the good work! :)
--
Lloyd Zusman 01234567 <-- The world famous Indent-o-Meter.
l...@panix.com ^ I indent thee.
To get my PGP public key automatically mailed to you, please
send me email with the following string as the subject or on a
line by itself in the message (leave off the quotation marks):
"mail-request public-key"
>When will this be available to run under Unix? Is this freeware, or
>proprietary?
Hamilton C shell is a proprietary product, reflecting the 7 years
full-time and over 115,000 lines of code it's taken to produce it.
(As you can guess from that, there is indeed more than just a C shell
there; there's also most all the usual utilities like grep, fgrep, ls,
mv, cp, rm, diff, head, tail, sed, strings, cron, tar, etc., etc.)
The price for either the NT or the OS/2 version is $350 in the US,
including shipping by air. (Outside the US, it's a bit higher,
reflecting my actual increased costs for marketing, shipping and support.)
I do not charge for bug fixes or support. I figure my customers
have paid for a working product. If a customer finds a bug, I
fix it. Period. If they have a question or need help, they get
it. Doesn't matter how long they've had the product. I offer
an unconditional satisfaction guarantee, which means just what it
sounds like. A lot of my motivation for quiting my job and risking
everything to start this 7 years ago was that this is what I wanted
to do with my life. It means a lot to me to say I'm going to do
whatever it takes to make my customers happy and I'm not going to
ask for permission to do that.
As I said in my previous post, I have had some requests from customers
for a UNIX version. Typically, they had bought my product for OS/2
or NT because they were moving to one of those platforms and needed
an environment that could give them the same productivity they'd
enjoyed under UNIX. Then they get hooked on the improvements and
find they don't like their UNIX shells any more. Unfortunately, I
don't right now have plans to produce a version for UNIX nor do I
know yet if it will ever happen.
There are several parts to the problem for me in building a UNIX
version. One problem, until recently, was purely technical: I'd
architected the code around the assumption of threads -- and most
UNIX systems didn't have threads. That's not at all an easy
assumption to undo. That use of threads really is woven tightly
into the "fabric" of the design. Of course, now more and more
UNIX systems do support threads, so that problem is dissipating,
but the business questions remain.
First, there's the obvious question of the business case: frankly,
it's very difficult to compete against anything free, even if you
are much, much better. UNIX does have a C shell, however crippled,
and it is free. OS/2 and NT were more open territory: neither
came with any UNIX-style shell at all. Of course, the converse
is that on UNIX, you might find more people who like the C shell
but just don't like its failings and would be more willing and
able to pay for the improvement. The point is that this is a
question to which I don't currently have an answer. Maybe I could
make a UNIX version pay for itself, maybe I couldn't.
Second, and really, probably more important, is the question of
resources. I'm a one-person operation. I'm both president and
janitor in my business. I have only the same number hours in a
day as you do. When I spend money to buy a new machine, that's
money I take away from what my family might spend on something
else. For years, the not so funny (but true!) joke was that we
had a couch in the with broken springs because I just couldn't
afford to replace it. In the last couple years (thanks to sales
of NT), we've come out of that state of near poverty, but I still
have to watch things carefully. Right now, I've got 4 machines
staring at me so I can support all my current versions. If I
undertook to support UNIX, how many more machines would I have
to buy, for example?
To entertain a UNIX version, I need to satisfy myself that that
would be the _best_ use of my limited time and financial
resource. That's some tough competition, as I can promise
you there are always many more good ideas (a _lot_ of the best
coming from some wonderful customers!) than I have time to
work on.
I don't mean to sound like I have my hand out for this, but I
suppose the most obvious thing that might motivate me to get
going on a UNIX version would be a customer coming to me and
saying they wanted it badly enough they'd make me an offer I
couldn't refuse. :-)
>I would like to vote for '2>x', or if you don't like that specific
>notation, SOME way to redirect stderr without stdout. I use this
>functionality frequently, and the absence of the ability to easily do
>this is what finally drove me away from 'csh' for good. With all the
>really nice features of your rewritten C shell, I would still end up
>not using it much if I couldn't redirect stderr alone ... and this
>would be unfortunate, because I am quite impressed with what you have
>done.
Well, as I said, 2>x notation hasn't yet made it into the product
but, without making specific promises, I think it will. The
language issues I raised notwithstanding, I agree the functionality
is worth having.
By the way, I appreciate your encouraging remarks. Thank you very
much!
I did try with bash, and it worked. This is what I've done:
testbash(){
> for i in `cat /tmp/vmunix.uu`
> do
> echo "This is argument $i." >> /tmp/log
> done
> }
where /tmp/vmunix.uu is 5000 lines long uuencoded kernel, of length over
300K, full of spaces (it could have been longer, but it would have taken a
long long time, since my machine is not the essence of speed). I started it
and got (after several minutes) a proper log file with exactly what you can
expect:
> This is argument begin.
> This is argument 755.
> This is argument vmunix.
> This is argument M.
> This is argument 0,!!P.
> This is argument 48.
> This is argument U38.
> This is argument ';F.
and so on.
> wc -l log
> 58214 log
I tried with longer files, but it just took too much to wait, the shell
didn't report any error. I don't know if everything is 'totally dynamic' in
bash, but I know it's a great shell. You should withdraw the 'try this with
any other shell' statement.
Hrv
--
o o o o o o o . . .
o _____ ______________ __________________=======_||__
.][__n_n_|DD[ ====_______| | ETF Zagreb | | Hrvoje Niksic |
>(|| | | [H. Niksic ] | Croatia | | hni...@srce6.srce.hr |
)_______|__|_[___________]_|____________|_|____________________________|
_/oo QGQGQ oo 'ooo ooo 'o!o!o o!o!o 'o!o o!o
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-
would strip the X's from the lines thus enabling the script to extraxt some
text from itself. I think this is a very useful facility. Does your shell
support it?
> Still, Bill Joy did make some important contributions to shell
> design that I think even Tom will acknowledge. The overall style
> is, without question, more modern. All the reversed keywords --
> the esac's and fi's, etc. -- in the Bourne and Korn shells look,
> to my taste, pretty damn dated. Reading an sh or ksh script reminds
> me of CACM article ca. 1970. Why anyone would want to fool with
> that kind of junk in the 90's is beyond me. The C shell constructs
> reflect a lot more of what we know today about what a language
> should look like.
Why? I have seen csh and sh scripts, and csh do not look all that more
modern to me. Sh supports the braces, if, case, and many other things that
one might need for script programming, and is definitely more convenient for
that purpose than csh. The builtin evaluation and arrays are good things in
csh, but are also implemented in e.g. ksh, and so are in bash (with
exception of the arrays).
I agree that fi and esac look ugly, but they aren't that bad to work with.
Anyway, it's still much better than csh where you have two if-types, if and
if-then-endif, where the second form cannot be in one line, and the first
doesn't support else.
Concerning the history mechanism, it is a thing belonging to interactive
work, and we can all agree that neither sh nor csh are suitable for
interactive work; you can use bash or tcsh for those purposes.
Then what about POSIX compatibility. As far as I've been told, POSIX
standard for shells is primarily based on sh, and not csh. This is also one
of the best assets of bash.
> Today, Joy's C shell is not the only C shell in the world any more
> than UNIX is the only small multi-tasking operating system in the
> world. Myself, I am the author of Hamilton C shell for OS/2
> and Windows NT. This is a completely from-scratch recreation of the
> C shell for these newer operating systems. Not one line of code has been
> ported from anywhere else. Here are some of the basic architectural
> and feature differences:
Now, to be honest, I have to congratulate you on all this. It seems real good
(although I doubt that I would use it on UNIX instead of bash), and I
guarantee that if I ever start working on Windows NT, I shall try to
purchase a copy of Hamilton csh with it. Keep up the good work (and make
bash for NT and OS/2 :>)
>There is a very useful construct in sh that you failed to mention, and that
>is Document-here, I think it's called. For example:
>sed 's/^X/' > extract <<'END_OF_FILE'
>XSome text
>Xhere.
>END_OF_FILE
>would strip the X's from the lines thus enabling the script to extraxt some
>text from itself. I think this is a very useful facility. Does your shell
>support it?
Yes, the here document stuff works just as you'd expect. Here's
your example, cut 'n pasted from another window on my screen where
I ran it with my C shell and my sed:
7 I% sed 's/^^X/' <<'END_OF_FILE'
8 I? XSome text
9 I? Xhere.
10 I? END_OF_FILE
Some text
here.
11 I%
(I had two ^'s in there only because I have my escape character
set to the ^, OS/2 and NT-style. If I had it set to the \, UNIX-
style, there'd have been only one ^ there.)
> ... Sh supports the braces, if, case, and many other things that
>one might need for script programming, and is definitely more convenient for
>that purpose than csh. The builtin evaluation and arrays are good things in
>csh, but are also implemented in e.g. ksh, and so are in bash (with
>exception of the arrays).
Clearly, you're comparing sh/ksh against Joy's C shell,
not mine. I'm going to paste a couple sample scripts
onto the end of this that generate a calendar for any
desired month. If you do it for the current month, it
highlights today's date. I'm sure some bright fellow can figure
out a way to do it in sh/ksh (heck, there's probably
someone who could do it with sed!), but I'm going to be darn
surprised if it's as easy.
Btw, these scripts use NO external utilities except the date command
(called dt.exe on OS/2 and NT so it won't conflict with the ones that
come with the operating system.) Everything else you see -- all
the string operations, the printf, the ANSI escape sequence generation,
etc. -- is all built right into the C shell.
My point in showing you these scripts is not to suggest anyone should
buy my C shell to print calendars but to demonstrate that its scripting
capabilities are very clearly NOT limited to just the sort of simple
stuff you normally think of doing with your shell.
To give you an idea of the performance, here's a sample run
on an ancient 16MHz 386 running OS/2 1.3:
24 I% time calendar december 1950
December 1950
Sun Mon Tue Wed Thu Fri Sat
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
0:00:03.19
(On something like my DEC Alpha, the execution time for
this script drops to about 1/10 what you see here.)
As you'll see if you look at the scripts, the calendar
script and the julian date script it calls are what I
call "self-loading" procedures. I won't bore you with
a repeat of the same output, but running this a second
time, it takes only .88 seconds on that same machine because
the compiled code is already now sitting in memory.
(Btw, a couple notes on reading the scripts: the // expression
operator is integer division; the escape character is set
to ^ (NT or OS/2-style) here, so ^ at the end of the line
means ignore the line end.)
>I agree that fi and esac look ugly, but they aren't that bad to work with.
I understand it's possible to get used to limp, too! :-)
>Anyway, it's still much better than csh where you have two if-types, if and
>if-then-endif, where the second form cannot be in one line, and the first
>doesn't support else.
Again, your comparison is against Joy's C shell, not mine. Mine
works correctly. Here's an example cut 'n pasted from another
window on my machine:
17 I% if (5+2 == 7) then echo correct; else echo oh-oh; end
correct
>Concerning the history mechanism, it is a thing belonging to interactive
>work, and we can all agree that neither sh nor csh are suitable for
>interactive work; you can use bash or tcsh for those purposes.
You keep comparing against Joy's C shell. In a side-by-side
comparisons of the full-screen command line editing (and all the
filename and command completion that completion that comes with
it) in my C shell against anything else, I think you'd be
satisfied mine is better.
>Then what about POSIX compatibility. As far as I've been told, POSIX
>standard for shells is primarily based on sh, and not csh. This is also one
>of the best assets of bash.
Re: POSIX, well, yes, they did standardize on sh/ksh, not csh.
What can I say? By the time something's a standard, you can bet
there's not a lot more real frontier work being done on it;
instead, the committees take over with position papers and votes,
etc.
I'm trying to advance the art; anyone can just copy exactly what
a standard specifies.
>Now, to be honest, I have to congratulate you on all this. It seems real good
>(although I doubt that I would use it on UNIX instead of bash), and I
>guarantee that if I ever start working on Windows NT, I shall try to
>purchase a copy of Hamilton csh with it. Keep up the good work (and make
>bash for NT and OS/2 :>)
Thank you. If you ever do find yourself using it on NT, I think
you'll be pleased.
Regards,
Doug Hamilton KD1UJ hami...@bix.com Ph 508-440-8307 FAX 508-440-8308
Hamilton Laboratories, 21 Shadow Oak Drive, Sudbury, MA 01776-3165, USA
------- calendar.csh -------
# Print a calendar for the specified month, highlighting today's date.
# Based on algorithms published in Computer Language magazine,
# December, 1990. Used with permission.
proc day(jdate)
# Calculate the day of the month corresponding to a Julian day number.
local a, b, c, d, e, z, alpha
@ z = jdate + 1
# Cope with the Gregorian calendar reform.
if (z < 2299161) then
@ a = z
else
@ alpha = (z - 1867216.25)//36524.25
@ a = z + 1 + alpha - alpha//4
end
@ b = a + 1524
@ c = (b - 122.1)//365.25
@ d = floor(365.25 * c)
@ e = (b - d)//30.6001
return b - d - floor(30.6001 * e)
end
proc dayofweek(jdate)
return (jdate + 2) % 7
end
proc calendar(month, year)
# Print a calendar for the specified month
local b_date, e_date, c_date, day, c_day, c_month, c_year, Month, week
local m, d, y, i, today
set Month = January February March April May June ^
July August September October November December
set dt = `dt`
set m = $dt:1
set d = $dt:2
set y = $dt:3
for i = 0 to 11 do
if (m == substr(Month[i], 1, 3)) break
end
@ m = i + 1
@ today = `julian $m $d $y`
if (year == '') then
@ year = y
if (month == '') @ month = m
end
if (month !~ '[0-9]*') then
@ m = "$lower(month)*"
for i = 0 to 11 do
if (lower(Month[i]) =~ m) break
end
@ month = i + 1
end
# Calculate Julian day numbers for the first and last days of the month
if ((b_date = julian(month, 1, year)) == -1) return
@ e_date = (month < 12 ? ^
julian(month + 1, 1, year) : ^
julian(1, 1, year == -1 ? 1 : year + 1)) - 1
echo $Month[month - 1] $year
@ week = "^r^nSun Mon Tue Wed Thu Fri Sat^r^n"
# Put the first day of the month under the correct day column
for i = 0 to day = dayofweek(b_date) - 1 do
@ week = concat(week, " ")
end
# Print all the days
@ i = 1
if (b_date == 2299156) then
# In October 1582, the Julian calendar was replaced with the
# Gregorian calendar and Oct 4 was immediately followed by Oct 15
# by decree of Pope Gregory XIII. However, be aware that Britain
# did not adopt the Gregorian calendar until Sept 2, 1752 (which
# was followed by Sept 14.) This routine prints a calendar according
# to Pope Gregory's decree.
for c_date = b_date to e_date do
@ week = concat(week, printf("%3d ", i++))
if (i == 5) @ i = 15
if (c_date != e_date && ++day % 7 == 6) @ week = concat(week, "^r^n")
end
else
for c_date = b_date to e_date do
@ week = (today == c_date) ? ^
concat(week, ansi("bright yellow"), ^
printf("%3d ", i++), ansi()) : ^
concat(week, printf("%3d ", i++))
if (c_date != e_date && ++day % 7 == 6) @ week = concat(week, "^r^n")
end
end
calc week
echo
end
calendar $argv
------- julian.csh -------
# Calculate the Julian day number for the specified date.
# Based on algorithms published in Computer Language magazine,
# December, 1990. Used with permission.
proc julian(month, day, year)
# The Julian day number is the number of days between noon GMT
# Jan 1, 4713 BC and that date. (Years B.C. are negative.)
local a, b, year_corr, Month, i
set Month = January February March April May June ^
July August September October November December
if (year == '') then
local dt
set dt = `dt`
@ year = $dt:3
if (day == '') then
@ day = month == '' ? $dt:2 : month
@ month = $dt:1
end
end
if (month !~ '[0-9]*') then
@ month = "$lower(month)*"
for i = 0 to 11 do
if (lower(Month[i]) =~ month) break
end
@ month = i + 1
end
if (month < 1 || month > 12 || year < -4713 || year > 2900) then
echo -2 julian: Invalid Date
return -1
end
# Correct for negative year.
if (year < 0) then
@ year++
@ year_corr = 1
@ b = 1
else
@ year_corr = b = 0
end
if (month <= 2) then
@ year--
@ month += 12
end
# Cope with the Gregorian calendar reform
if (year * 10000 + month * 100 + day > 15821015) then
@ a = year//100
@ b = 2 - a + a//4
end
@ a = floor(365.25 * year - year_corr) + ^
floor(30.6001 * (month + 1)) + day + 1720994 + b
# 4713 BC was not a leap year.
if (a < 59) @ a++
return a
end
julian $argv
>In his article hamilton on BIX (hami...@BIX.com) wrote:
>> .... Want to iterate with a foreach
>> over a couple megabyte-long list of filenames? No problem. Try
>> that with any other shell.
>I did try with bash, and it worked. This is what I've done:
>testbash(){
>> for i in `cat /tmp/vmunix.uu`
>> do
>> echo "This is argument $i." >> /tmp/log
>> done
>> }
>where /tmp/vmunix.uu is 5000 lines long uuencoded kernel, of length over
>300K, full of spaces (it could have been longer, but it would have taken a
>long long time, since my machine is not the essence of speed). I started it
>and got (after several minutes) a proper log file with exactly what you can
>expect...
>I tried with longer files, but it just took too much to wait, the shell
>didn't report any error. I don't know if everything is 'totally dynamic' in
>bash, but I know it's a great shell. You should withdraw the 'try this with
>any other shell' statement.
Okay, so perhaps amend this to say, unlike Bash, where you can grow
old while it does this, my shell does it quickly enough to be useful.
Here's the actual test I had in mind, iterating over all the files
on my h:, i: and j: drives on my OS/2 1.3 machine. Notice that I'm
wildcarding drive letters with a range and using the "..." notation
to walk thru every file on every one of those drives. This is on an
ancient 16MHz 386 with 12M RAM, so I'm absolutely NOT pulling any
stunts here with super-fast hardware:
10 H% time (foreach i ([h-j]:\...\*) calc i; end | wc)
14072 14072 446090
0:01:31.10
[stuff deleted]
:Clearly, you're comparing sh/ksh against Joy's C shell,
:not mine. I'm going to paste a couple sample scripts
:onto the end of this that generate a calendar for any
:desired month. If you do it for the current month, it
:highlights today's date. I'm sure some bright fellow can figure
:out a way to do it in sh/ksh (heck, there's probably
:someone who could do it with sed!), but I'm going to be darn
:surprised if it's as easy.
[rest of commercial deleted]
List, don't take this the wrong way, but I'm really sick and tired of
hearing about your csh vs. Bill Joy's csh. The fact of the matter is
that one of the aforementioned csh's is available on almost every
single UNIX box one comes in contact with, and the other is being sold
by you!
So... You'll have to pardon people who say that C-shell programming is
the pits compared to Bourne/Korn shell programming.
If you want to release your shell to be used for free like zsh, tcsh,
bash, ash, etc, then by all means release it and tell us all about it.
If you want to sell it, then please don't waste bandwith posting
commerical advertisements!
Thank you.
--Jerry
--
|> Jerry Alexandratos ** "vengo de la tierra del <|
|> alex...@louie.udel.edu ** fuego ten cuidado cuando <|
|> dark...@chopin.udel.edu ** llamas mi nombre..." <|
Unlike the person above, I have found the comments made by Doug Hamilton
very useful. As an NT developer who comes from a Unix environment and
happens to like the C Shell, I want to know what is available for NT and
what differences there are from the standard C Shell. In the time that
I've read this newsgroup, I have found Doug's answers to various questions
useful, and I don't begrudge him a little advertising space.
Currently, I am using the MKS Korn shell, but I may be giving Doug a call
one of these days to get his C Shell, especially after reading some of his
recent "commerical advertisements" in this group.
Gordon Chaffee
cha...@bugs-bunny.cs.berkeley.edu
In article <hamilton....@bix.com> hami...@BIX.com
(hamilton on BIX) writes:
:hni...@srce6.srce.hr (Hrvoje Niksic) writes:
[stuff deleted]
[rest of commercial deleted]
List, don't take this the wrong way, but I'm really sick and tired
of hearing about your csh vs. Bill Joy's csh. The fact of the
matter is that one of the aforementioned csh's is available on
almost every single UNIX box one comes in contact with, and the
other is being sold by you!
So... You'll have to pardon people who say that C-shell
programming is the pits compared to Bourne/Korn shell programming.
If you want to release your shell to be used for free like zsh,
tcsh, bash, ash, etc, then by all means release it and tell us all
about it.
If you want to sell it, then please don't waste bandwith posting
commerical advertisements!
Thank you.
--Jerry
I'm disappointed at this flame directed at Doug Hamilton, who I
consider to be one of the most informative posters on the net. At
least, he is one of the few people whose posts I look *forward* to
reading. While he does have a commercial product, and he does
mention it in appropriate contexts, I have never seen him post
anything that I would consider blatant advertising at all.
His product is commercial - so what? Lots of good products
are commercial. GNU doesn't do the best of everything, and not
everyone gets donations to pay their bills.
I look forward to reading a lot more from Doug Hamilton in
the future.
Cheers,
Tony.
--
_____________________________________________________________________________
A.B.Coates, Dept. of Physics,
The University of Queensland QLD 4072 Australia.
Email: coa...@physics.uq.oz.au
Phone: (07/+617) 365-3424 Fax: (07/+617) 365-1242
Disclaimer: The University is ignorant of my
opinions, let alone guilty ...
_____________________________________________________________________________
Agreed.
>When will this be available to run under Unix? Is this freeware, or
>proprietary?
>
>> 1. File descriptors. Tom devotes a lot of space to complaining about
>> the C shell's lack of support for the 2>x notation for redirection.
>
>I would like to vote for '2>x', or if you don't like that specific
>notation, SOME way to redirect stderr without stdout.
I'd vote for >[x] (if you use es, this will be very familiar :-).
It's pretty hard to confuse with something else (ie. the fd index is *after*
the >, so no parsing problems, and the [x] is right after the >, again -
no parsing problems).
Actually, a lot of what you've done looks like tcsh (bug fixes, etc), but
different (better in some cases)... Interesting to see parallel development
in csh...
James Ojaste
--
fn info guess {if {~ $guess 'James Ojaste'} {echo Right!} {~ $guess es-lover} {
echo Yup} {~ $guess joj...@descartes.uwaterloo.ca} {echo Uh-huh} {echo Bzzzt}}
> Unlike the person above, I have found the comments made by Doug Hamilton
> very useful. As an NT developer who comes from a Unix environment and
> happens to like the C Shell, I want to know what is available for NT and
> what differences there are from the standard C Shell. In the time that
I've spoken to a number of C shell lovers who have used the "Hamilton C Shell".
Most of them have said that it may be a lot of things, but the c shell it
ain't. Doug's shell is the hamilton reinterpertation of the c shell. Lots
of functions are different in from small to large ways to fit doug's personal
vision of what the c shell should be. That also goes for the included
utilities. Doug's proud of the fact that there are perhaps thousands
of man years worth of freely available unix technology that he ignores.
> Currently, I am using the MKS Korn shell, but I may be giving Doug a call
> one of these days to get his C Shell, especially after reading some of his
> recent "commerical advertisements" in this group.
You should. Let us know if its really the c shell
--
----
Art Kreitman Congruent Corporation
ar...@congruent.com 110 Greene Street
212-431-5100 New York, New York 10012
fax 219-1532
There is only one true C shell. That's Joy's. Calling your beefed up
8-track superduper C-shell-LIKE-creature modern C shell is at least
misleading. Please call your pet ntcsh or bill_the_gatesh or
Hamiltonsh or...any lawyer here want to make some money with Mr. Joy?
>Btw, these scripts use NO external utilities except the date command
>(called dt.exe on OS/2 and NT so it won't conflict with the ones that
>come with the operating system.) Everything else you see -- all
>the string operations, the printf, the ANSI escape sequence generation,
>etc. -- is all built right into the C shell.
I don't know who cross-posted the crap to comp.UNIX.shell, please confine
NT and/or OS/2 ramblings to comp.os.ms-windows.nt.misc or
comp.os.os2.advocacy.
>My point in showing you these scripts is not to suggest anyone should
>buy my C shell to print calendars but to demonstrate that its scripting
>capabilities are very clearly NOT limited to just the sort of simple
>stuff you normally think of doing with your shell.
Yeah, we just use /usr/bin/cal to print calendar, pick a more useful
example next time...
For normal shell programming chores:
If I want compatibility, I use POSIX sh or even vanilla Bourne-shell;
if I want functionality/flexibility/speed, I use Perl;
BTW, my interative shell is still tcsh, I don't see any problem...
They are all freely available/present on almost all unix platforms, what
about your hamiltonsh? Advertising a NT program in a UNIX group will get
your nowhere. (Followup redirected as appropriate).
__Luke
I do not know whether in sh is called "document-here", but in
csh it is called "here-document" and does exist exactly as shown !
--
----------------------------------------------------------------------------
A member of G.ASS : Group for Astronomical Software Support
----------------------------------------------------------------------------
Lucio Chiappetti - IFCTR/CNR | Ma te' vugl' da' quost avis a ti' Orsign
via Bassini 15 - I-20133 Milano | Buttet rabios intant te se' pisnign
Internet: LU...@IFCTR.MI.CNR.IT |
Decnet: IFCTR::LUCIO | (Rabisch, II 46, 119-120)
----------------------------------------------------------------------------
From: ar...@Congruent.COM (Arthur Kreitman)
Newsgroups: comp.unix.shell,comp.os.ms-windows.nt.misc
Date: 21 Nov 94 14:39:34 GMT
Followup-To: comp.unix.shell
Organization: Congruent Corporation; New York, NY
I've spoken to a number of C shell lovers who have used the "Hamilton C
Shell".
Most of them have said that it may be a lot of things, but the c shell it
ain't. Doug's shell is the hamilton reinterpertation of the c shell. Lots
of functions are different in from small to large ways to fit doug's
personal
vision of what the c shell should be. That also goes for the included
utilities. Doug's proud of the fact that there are perhaps thousands
of man years worth of freely available unix technology that he ignores.
----
Art Kreitman Congruent Corporation
ar...@congruent.com 110 Greene Street
212-431-5100 New York, New York 10012
fax 219-1532
This reminds me of another posting from the very same Art Kreitman about the
Ataman Software telnet demon:
>
> Now that's what every buyer want's to hear, that a critical product
>for their firm comes from a company that consists of a student at a
>grade b CS school operating from a kitchen table. And the dog does
>tech support.
BTW Art, if you are so fond of these "thousands of man years worth of
freely available unix technology", why do you charge so much for the
Congruent UNIX CD? It seems to me that you are making money with other
people's labour, whereas Doug Hamilton only wants to be able to live from
his own work.
Cheers,
--
--------------------------------------------
Henrik Nordborg
Institute of Theoretical Physics
Swiss Federal Institute of Technology (ETH)
CH-8093 Zurich
phone: +41-1-633 25 73
fax: +41-1-633 11 15
hen...@itp.phys.ethz.ch
--------------------------------------------
> I've spoken to a number of C shell lovers who have used the "Hamilton C Shell".
>Most of them have said that it may be a lot of things, but the c shell it
>ain't. Doug's shell is the hamilton reinterpertation of the c shell. Lots
>of functions are different in from small to large ways to fit doug's personal
>vision of what the c shell should be. That also goes for the included
>utilities. Doug's proud of the fact that there are perhaps thousands
>of man years worth of freely available unix technology that he ignores.
It is true that I am proud of my product. I've put seven years of
very hard work into making it the best I know how. And yes, it is
true that every line of code in the product is mine. I made the
design choices. I wrote it. I am responsible.
But contrary to what Art implies, I freely acknowledge that many of
the most important ideas in my product have been suggested by others.
Whatever I have accomplished, it is because of the contributions of
others who have come before me.
What Art neglects to mention is that he is a competitor who makes
his money by selling GNU software. On this particular occasion, he
is at least treating me better than he treats many people. Readers
of the comp.os.ms-windows.programmer.win32 topic will well remember
some of Art's choicer words back in May to customers complaining
that he had failed to deliver promised source to the binaries he
was selling.
In that discussion, I and his other competitors sat quietly on the
sidelines, viewing it as rather unseemly to offer comment.
Obviously, Art and I disagree on a *lot* of philosophical issues.
>There is only one true C shell. That's Joy's. Calling your beefed up
>8-track superduper C-shell-LIKE-creature modern C shell is at least
>misleading. Please call your pet ntcsh or bill_the_gatesh or
>Hamiltonsh or...any lawyer here want to make some money with Mr. Joy?
Oh yeah? Mr. Joy trademarked "Hamilton C Shell?" Doubt it. Hamilton
can name his shell whatever the hell he wants. If he thinks it's a
C shell in the same way the Joy's csh is, he can call it a C Shell.
>I don't know who cross-posted the crap to comp.UNIX.shell, please confine
>NT and/or OS/2 ramblings to comp.os.ms-windows.nt.misc or
>comp.os.os2.advocacy.
As the ravenous, sharp-toothed mammals encircled the great beast, the
lumbering dinosaur sprayed urine around the edge of its realm, marking
the boundaries of its shrinking territory.
Heath
: I'm disappointed at this flame directed at Doug Hamilton, who I
: consider to be one of the most informative posters on the net. At
: least, he is one of the few people whose posts I look *forward* to
: reading. While he does have a commercial product, and he does
: mention it in appropriate contexts, I have never seen him post
: anything that I would consider blatant advertising at all.
I agree completely. Doug is a valued contributor to the Windows NT and
Win32 newsgroups who has plainly avoided abusive advertising. In every
case I can recall, Doug's mentions of his product have been in response
to questions about shells or Unix-like utilities for Windows NT, which is
perfectly appropriate.
If you do not want to read them, use the Kill feature available in most
all newsreaders.
--- dave...@eskimo.com - http://www.eskimo.com/~davehart/
I work for Microsoft, but my opinions in no way represent
the opinions of Microsoft Corporation.
Oh, please. Somehow I'm unsurprised that you would fail to mention as
you disparage Doug and his products that you are a competitor of sorts,
repackaging barely-ported GNU software for Windows NT and collecting $200 a
pop.
For the benefit of those of you who weren't here a few months ago, there
was quite a flare up in the comp.os.ms-windows.nt.misc newsgroup about Art
and his company and his now-ceased practice of intimidating his customers
to believe that the modified GNU source code to his product belonged to
him and could not be resdistributed, when in fact it was all licensed to
ARt under the GNU Public License which requires modified source code be
made available for cost of media. After some pressure Art finally backed
down and stopped claiming ownership.
Art, how aut some customer testimonials for your shell? Everyone I've
talked to who has tried it has given it up.
>I tried with longer files, but it just took too much to wait, the shell
>didn't report any error. I don't know if everything is 'totally dynamic' in
>bash, but I know it's a great shell.
And also rc has no problems with this size of argument list - not
very surprisingly as *any* decent shell should allocate such memory
dynamically:
; uuencode /vmunix vmunix > xx
; wc xx
39986 320178 2478941 xx
; rc -c 'for(ii in `{cat xx}) {echo Arg $ii}' > zz
; wc -l zz
320178 zz
> You should withdraw the 'try this with
>any other shell' statement.
Indeed. I'd propose to repeat the tests with modern versions of all
Unix shells and then to think twice about the direct comparisons in
the original message.
Stefan
---
Stefan Dalibor dal...@immd3.informatik.uni-erlangen.de
http://faui30t.informatik.uni-erlangen.de:1200/Staff/dalibor/dalibor.html
The louder you scream, the faster we go.
Yes, I see that you're right, and I apologize for speaking before searching
through csh well enough. Furthermore, I garbled things. sed 's/^X/' should
have been sed 's/^X//'.
Sorry once again for the mistake. But csh is still terrible. The classical
example with repeat 3 echo "/vmu*" still works on my shell ;)
Other than csh and your shell, what other C shells are there?
=Myself, I am the author of Hamilton C shell for OS/2
=and Windows NT. This is a completely from-scratch recreation of the
=C shell for these newer operating systems. Not one line of code has been
=ported from anywhere else. Here are some of the basic architectural
=and feature differences:
What will happen to a csh script run under your shell?
=A good C shell that addresses the complaints Tom voices is not
=only possible, it exists today. Now, I admit, if you're still
=stuck on UNIX, you're still stuck with Joy's version
Oh. Never mind.
>Other than csh and your shell, what other C shells are there?
There have been a couple others offering varying degrees of
compatibility with Bill Joy's original C shell. One was the
Thompson shell for DOS, which I believe has been gradually
rewritten over the years to be Korn shell compatible, and
the other was by Allen Holub, well-known for his compiler
book, also for DOS.
>What will happen to a csh script run under your shell?
Most scripts written for the original C shell run with minimal
modification, thanks to a Berkeley compatibility mode in my
shell. If you run a script that starts with #!/bin/csh, my
C shell assumes it's an older script written to run according
to the rules of Joy's C shell. It disables some of the new
enhancements and reverts to the older style in other ways also.
> In article <3an84d$i...@agate.berkeley.edu>
cha...@bugs-bunny.cs.berkeley.edu (Gordon Chaffee) writes:
>
>
> > Unlike the person above, I have found the comments made by Doug Hamilton
> > very useful. As an NT developer who comes from a Unix environment and
> > happens to like the C Shell, I want to know what is available for NT and
> > what differences there are from the standard C Shell. In the time that
>
> I've spoken to a number of C shell lovers who have used the "Hamilton
C Shell".
> Most of them have said that it may be a lot of things, but the c shell it
> ain't. Doug's shell is the hamilton reinterpertation of the c shell. Lots
> of functions are different in from small to large ways to fit doug's personal
> vision of what the c shell should be. That also goes for the included
> utilities. Doug's proud of the fact that there are perhaps thousands
> of man years worth of freely available unix technology that he ignores.
>
>
> > Currently, I am using the MKS Korn shell, but I may be giving Doug a call
> > one of these days to get his C Shell, especially after reading some of his
> > recent "commerical advertisements" in this group.
>
> You should. Let us know if its really the c shell
>
If you use Doug's features, then your script will be 0% portable. I
wouldn't recomend it. sh or ksh as well as perl would be a better choice
for portability. Maybe is Doug shipped sliced down shareware/demoware for
other UNIXes, there would be some portability. But, even then it still
wouldn't be truely portable.
MKS looks better for portability reason. Also, I'm sure Perl is ported to
NT too. Another language to keep an eye out for is ObjectREXX.
- Dan
--
"One does not seriously attack the expertise of a scientist,
using the undefined phrase 'butt-head.'"