我在 tcsh 中遇到重定向问题。
考虑以下命令:vi --version
和vi --xxx
。我们假设这是在vi
支持该--version
选项的机器上。该选项--xxx
无效,因此vim
应该通过 来显示一些内容stderr
。
根据这个推理,2> /dev/null
与这两个命令一起使用应该为有效情况提供输出,而为无效情况不提供输出。
然后是我在 bash、zsh、ksh 和 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)
...
然而,当我在 tcsh 中尝试这个时,它给了我无输出在两个都案例。
$ vi --xxx 2> /dev/null
$ vi --version 2> /dev/null
(there is no output here)
这里发生了什么?我重定向stderr
错误吗?
这是输出tcsh --version
:
tcsh 6.18.01 (Astron) 2012-02-14 (i686-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
答案1
这种不一致实际上是原因列表中的第一个原因csh 编程被认为是有害的。
或者如果您只想扔掉 stderr 并保留 stdout 该怎么办?操作很简单吧?
cmd 2>/dev/null
在 Bourne shell 中工作。在csh中,只能做这样的可怜尝试:
(cmd > /dev/tty) >& /dev/null
但谁说 stdout 是我的 tty?所以这是错的。这个简单的操作无法完成在csh中。
答案2
2>
不是 中的运算符tcsh
,您正在使用该>
运算符并2
作为参数传递给vi
。这出现就可以了,因为--xxx
和--version
exit vi
。
从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.
所以你可以使用>&
重定向两个都标准输出和标准错误(“诊断输出”)。没有“明显”的方法仅有的重定向stderr,这是C shell的一个长期存在的缺点,一个众所周知的解决方法是:
(vi --xxx > /dev/tty) >& /dev/null
这是通过将 stdout 重定向到/dev/tty
子 shell 中的(当前的 tty)(括号的作用与 bourne shell 中相同)来实现的,并且子 shell 的输出(因为我们重定向了 stdout,所以只是 stderr)被重定向到/dev/null
(但是这个可以是任何东西,比如文件)。
我不知道您的目标是什么,但在您无法确定用户正在使用什么 shell 的情况下,我发现通常最好显式设置它;有比“bourne 和 csh”更多的 shell,例如 Fish,并且不同的 Bourne shell 之间也可能存在轻微的不兼容性和/或某些结构可能“碰巧”在一个 shell 中工作,但在另一个 shell 中却不起作用...