Inconsistência do redirecionamento stderr entre tcsh e outros shells

5

Estou com problemas de redirecionamento no tcsh.

Considere os seguintes comandos: vi --version e vi --xxx . E vamos supor que isso esteja em uma máquina na qual vi suporta a opção --version . A opção --xxx é inválida e, portanto, vim deve exibir algo por meio de stderr .

Por esse raciocínio, usar 2> /dev/null com esses dois comandos deve fornecer saída para o caso válido e nenhuma saída para o caso inválido.

E isso é o que eu vejo em bash, zsh, ksh e 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)
...

No entanto, quando eu tento isso no tcsh, ele me dá nenhuma saída em ambos casos.

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

O que está acontecendo aqui? Estou redirecionando stderr incorretamente?

Se isso ajudar, aqui está a saída de tcsh --version :

tcsh 6.18.01 (Astron) 2012-02-14 (i686-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
    
por Sildoreth 22.04.2015 / 15:31

2 respostas

10

Esta inconsistência é, na verdade, a primeira razão na lista de motivos pelos quais a programação csh é considerada prejudicial a>.

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.

    
por 22.04.2015 / 15:40
3

2> não é um operador em tcsh , você está usando o operador > e passando 2 como um argumento para vi . Isso aparece para ficar bem, já que --xxx e --version exit vi .

De 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.

Portanto, você pode usar >& para redirecionar ambos stdout e stderr ( "output de diagnóstico" ). Não há nenhuma maneira "óbvia" de somente redirecionar o stderr, e essa é uma lacuna de longa data do shell C, uma solução conhecida é:

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

Isso funciona redirecionando stdout para /dev/tty (que é o tty atual) em uma subshell (os parentes fazem o mesmo que em bourne shells) e a saída da subshell (que é apenas stderr desde que redirecionamos stdout) é redirecionado para /dev/null (mas isso pode ser qualquer coisa, como um arquivo).

Eu não sei qual é o seu objetivo, mas nos casos em que você não pode ter certeza de qual shell o usuário está usando, descobri que geralmente é melhor defini-lo explicitamente; há mais conchas do que "bourne e csh", como peixes, e também pode haver pequenas incompatibilidades entre diferentes conchas Bourne e / ou algumas construções podem "acontecer" de funcionar em uma concha, e não em outra ...

    
por 22.04.2015 / 16:21