writing
teaching
speaking
photography
consulting
biography
weblog
contact
header-right2 home home bio

Wicked Cool Linux

<<     Column 3: Making C Shell (csh) Jump Through Hoops!     >|
By Dave Taylor

This column originally appeared in the October, 2004 issue of LinuxWorld Magazine and is reproduced here under the Creative Commons license. Learn more.

By this point in our discussion, you should be comfortable with the idea of the three file descriptors associated with the Linux command line: stdin, stdout and stderr (pronounced standard in, standard out and standard error). If you're using a descendant of the Bourne Shell (such as Bash) you also learned last month about how to use the x>&y notation to redirect the different descriptors from the command line, and therefore from within a script too. This time I'll turn my attention to the C Shell with its different command line syntax.

My focus here is ultimately on shell scripting, so I have to point out that the vast majority of Linux shell scripts are written in a Bourne Shell compatible scripting environment, whether it's directly in /bin/sh or in a more sophisticated environment like Bash. It's not that Csh and Ksh aren't good interactive shells, it's just that diversity breeds incompatibility and confusion rather than any sort of long-term advantage from the scripters perspective.

You'll have to make your own decision on what shell forms the basis of your scripting environment, but my strong recommendation is to work with Bash or a similar shell. In future columns, I won't spend much time at all on C Shell scripting methods and structures, so if you think that's a major problem, please email me and let me know!

Redirecting Stderr within Csh

There are couple of basic redirections that you'll want to know how to accomplish within the Csh environment, the most important of which is to redirect stderr (standard error) to the same place as stdout (standard out). This is perhaps the easiest to accomplish:

wc -l does-not-exist >& my.output

This notation - the added & after the redirect symbol - causes stderr to be mapped to the same place as stdout, that is, to the file my.output.

One problem that might occur is that the output file might already exist and you might have wisely set noclobber (that is, included the line set noclobber in your .cshrc) to try and minimize errors with overwritten files. The general notation for forcing an overwrite in this situation is to add an exclamation mark:

wc -l does-not-exist >! existing-output-file

We can slip in an ampersand and have a redirect that overrides noclobber and sends both stdout and stderr to the file, all at once:

wc -l does-not-exist >&! existing-output-file

Personally, I find this a bit confusing because of what us geeks call function overloading: at the end of a line, the & means that the job should be run in background, and followed by a number or pattern, ! is a reference to the previous command history in Csh. Hopefully your brain can untangle all of this more easily!

Oh, did I mention that you could append output to files just as easily with these redirects? Simply use >> where you'd otherwise use >, as in:

wc -l does-not-exist >>&! existing-output-file

However, if that doesn't look like the cat jumping on the keyboard, I don't know what will!

Unlike Bash, you cannot split out stderr in Csh to route it elsewhere, so it's not as flexible a mechanism. Your choices are either to have stderr go to the console, the default behavior, or to have it duplicate the destination of stdout.

Within a pipe, you can map stderr to stdout just as you can in a file redirect, and the notation should be logical and no surprise:

wc -l somefile |& grep -i error

This command tries to count the number of lines in "somefile", sending both stdout and stderr to the grep command via a pipe (without the & in the pipe notation, of course, stderr would go to the screen and grep would never see it. A very common mistake for neophyte scripters!). The grep command then simply looks for the word "error": the net result of this is that if "somefile" exists and wc can correctly count, there's no output, but if there's an error, the error message is displayed.

That's it for this column. Stay tuned as we get closer and closer to actually (gasp) writing a shell script or two!

Dave Taylor is a 25-year veteran of Unix, creator of The Elm Mail System, and most recently author of both the best-selling Wicked Cool Shell Scripts and Creating Cool Web Sites, among his sixteen technical books. His main Web site is at http://www.intuitive.com/