💾 Archived View for gemini.spam.works › mirrors › textfiles › programming › cshell.hrm captured on 2022-04-29 at 00:28:45.
⬅️ Previous capture (2020-10-31)
-=-=-=-=-=-=-
Newsgroups: comp.unix.shell,comp.unix.questions,news.answers From: Tom Christiansen <tchrist@convex.COM> Subject: Csh Programming Considered Harmful Message-ID: <1992Nov30.123449.8118@news.eng.convex.com> Date: Mon, 30 Nov 1992 12:34:49 GMT Organization: Convex Computer Corporation, Colorado Springs, CO Lines: 496 Archive-name: unix-faq/shell/csh-whynot Version: $Id: csh-faq,v 1.2 92/11/30 05:26:37 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 . 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 if 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. 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. Writing Files In the Bourne shell, you can open or dup random 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 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' Reading Files In the csh, all you've got is {body}lt;, 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 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. 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)