8

I'm running into issues with redirection in tcsh.

Consider the following commands: vi --version and vi --xxx. And let's assume this is on a machine where vi supports the --version option. The option --xxx is invalid, and therefore vim should display something via stderr.

By that reasoning, using 2> /dev/null with both of these commands should give output for the valid case and no output for the invalid case.

And that is what I see in bash, zsh, ksh, and dash.

$ vi --xxx 2> /dev/null
$ vi --version 2> /dev/null
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Oct 20 2014 16:09:17)
...

However, when I try this in tcsh, it gives me no output in both cases.

$ vi --xxx 2> /dev/null
$ vi --version 2> /dev/null
(there is no output here)

What is going on here? Am I redirecting stderr incorrectly?

Here is the output of tcsh --version:

tcsh 6.18.01 (Astron) 2012-02-14 (i686-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
12

This inconsistency is in fact the first reason in the list of reasons why csh programming is considered harmful.

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.

  • (expletive)! I was hoping that wouldn't be the case. – Sildoreth Apr 22 '15 at 13:44
  • 6
    Or sh -c 'cmd 2> /dev/null' – Stéphane Chazelas Apr 22 '15 at 13:55
  • 1
    @StéphaneChazelas that's cheating! :-) – Celada Apr 22 '15 at 14:01
  • the first reason in the last of reasons Is this a biblical reference, or a typo for “list”? – Emil Jeřábek supports Monica Apr 22 '15 at 22:10
  • @EmilJeřábek definitely a typo! Thanks for pointing it out. In fact, I don't even get the biblical reference. Probably because I'm not Christian, I guess. – Celada Apr 22 '15 at 22:21
4

2> is not an operator in tcsh, you're using the > operator and passing 2 as an argument to vi. This appears to be okay since both --xxx and --version exit vi.

From tcsh(1):

   > name
   >! name
   >& name
   >&! name
           The file name is used as standard output.  If the file does not
           exist then it is created; if the file exists, it is  truncated,
           its previous contents being lost.

           If  the shell variable noclobber is set, then the file must not
           exist or be a character  special  file  (e.g.,  a  terminal  or
           `/dev/null')  or an error results.  This helps prevent acciden‐
           tal destruction of files.  In this case the `!'  forms  can  be
           used to suppress this check.

           The  forms  involving  `&' route the diagnostic output into the
           specified file  as  well  as  the  standard  output.   name  is
           expanded in the same way as `<' input filenames are.

So you can use >& to redirect both stdout and stderr ("diagnostic output"). There is no "obvious" way to only redirect stderr, and this is a long-standing shortcoming of the C shell, a well-known workaround is:

(vi --xxx > /dev/tty) >& /dev/null

This works by redirecting stdout to /dev/tty (which is the current tty) in a subshell (the parens do the same as in bourne shells), and the output of the subshell (which is only stderr since we redirected stdout) is redirected to /dev/null (but this can be anything, like a file).

I don't know what your goal is, but in cases where you can't be sure what shell the user is using, I've found that it's usually best to explicitly set it; there are more shells than "bourne and csh", such as fish, and there may also be slight incompatibilities between different Bourne shells and/or some constructs may "happen" to work in one shell, and don't in another...

  • Note that sh -c 'cmd 2> /dev/null' happens to work in all the shells of the Bourne, csh, rc and fish families (on systems where sh is a Bourne-like shell). – Stéphane Chazelas Apr 22 '15 at 14:30
  • @StéphaneChazelas Yeah, that usually works for (very) simple commands, but it quickly becomes complex due to quoting issues, and people often make mistakes here. – Martin Tournoij Apr 22 '15 at 15:40
  • 1
    Yes, writing shell-agnostic code can be a bit tricky. (ツ) – Stéphane Chazelas Apr 22 '15 at 16:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.