Inkonsistenz der stderr-Umleitung zwischen tcsh und anderen Shells

8

Ich habe Probleme mit der Umleitung in tcsh.

Beachten Sie die folgenden Befehle: vi --versionund vi --xxx. Nehmen wir an, dies befindet sich auf einem Computer, auf dem vidie --versionOption unterstützt wird. Die Option --xxxist ungültig und vimsollte daher etwas über anzeigen stderr.

Aus diesem Grund sollte die Verwendung 2> /dev/nullmit diesen beiden Befehlen eine Ausgabe für den gültigen Fall und keine Ausgabe für den ungültigen Fall ergeben.

Und das ist , was sehe ich in bash, zsh, KSH, und Strich.

$ 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)
...

Wenn ich dies jedoch in tcsh versuche, wird in beiden Fällen keine Ausgabe ausgegeben .

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

Was geht hier vor sich? Leite ich stderrfalsch um?

Hier ist die Ausgabe von tcsh --version:

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

Antworten:

12

Diese Inkonsistenz ist in der Tat der erste Grund in der Liste der Gründe, warum die csh-Programmierung als schädlich angesehen wird .

Oder was ist, wenn Sie stderr einfach wegwerfen und stdout in Ruhe lassen wollen? Ziemlich einfache Bedienung, oder?

cmd 2>/dev/null

Funktioniert in der Bourne-Shell. In der csh können Sie nur einen erbärmlichen Versuch wie diesen machen:

(cmd > /dev/tty) >& /dev/null

Aber wer hat gesagt, dass stdout mein tty war? Also ist es falsch. Diese einfache Operation kann nicht in der csh durchgeführt werden.

Celada
quelle
(expletiv) ! Ich hatte gehofft, dass das nicht der Fall sein würde.
Sildoreth
6
Odersh -c 'cmd 2> /dev/null'
Stéphane Chazelas
1
@ StéphaneChazelas das betrügt! :-)
Celada
Der erste Grund im letzten Grund Ist dies eine biblische Referenz oder ein Tippfehler für „Liste“?
Emil Jeřábek
@ EmilJeřábek definitiv ein Tippfehler! Vielen Dank für den Hinweis. Tatsächlich bekomme ich nicht einmal den biblischen Bezug. Wahrscheinlich, weil ich kein Christ bin, denke ich.
Celada
4

2>ist kein Operator in tcsh, Sie verwenden den >Operator und übergeben 2als Argument an vi. Dies scheint in Ordnung zu sein, da beide --xxxund --versionbeenden vi.

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

Sie können also sowohl stdout als auch stderr >&umleiten ( "Diagnoseausgabe" ). Es gibt keinen "offensichtlichen" Weg, nur stderr umzuleiten, und dies ist ein seit langem bestehender Mangel der C-Shell. Eine bekannte Problemumgehung ist:

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

Dies funktioniert, indem stdout /dev/ttyin einer Subshell auf (das ist das aktuelle tty) umgeleitet wird (die Parens machen dasselbe wie in Borowski-Shells), und die Ausgabe der Subshell (die nur stderr ist, seit wir stdout umgeleitet haben) wird auf umgeleitet /dev/null(aber dies) kann alles sein, wie eine Datei).

Ich weiß nicht, was Ihr Ziel ist, aber in Fällen, in denen Sie nicht sicher sind, welche Shell der Benutzer verwendet, ist es normalerweise am besten, sie explizit festzulegen. Es gibt mehr Muscheln als "bourne and csh", wie z. B. Fische, und es kann auch zu geringfügigen Inkompatibilitäten zwischen verschiedenen Bourne-Muscheln kommen, und / oder einige Konstrukte können in einer Muschel "passieren" und in einer anderen nicht ...

Martin Tournoij
quelle
Beachten Sie, dass sh -c 'cmd 2> /dev/null'dies in allen Schalen der Familien Bourne, csh, rc und fish funktioniert (auf Systemen, in denen shes sich um eine Bourne-ähnliche Schale handelt).
Stéphane Chazelas
@ StéphaneChazelas Ja, das funktioniert normalerweise für (sehr) einfache Befehle, aber es wird aufgrund von Zitierproblemen schnell komplex und die Leute machen hier oft Fehler.
Martin Tournoij
1
Ja, das Schreiben von Shell-unabhängigem Code kann etwas schwierig sein . (ツ)
Stéphane Chazelas