在bash中重定向stdout和stderr的正确方法是什么?

时间:2013-09-04 21:56:37

标签: bash zsh

这是我正在努力完成的具体任务。 zsh表现得我喜欢的方式

$ zsh
$ which clang > /dev/null 2&>1 && echo clang || echo gcc
clang
$ which doesntexist > /dev/null 2&>1 && echo doesntexist || echo gcc
gcc

但是,在bash:

$ bash
$ which clang > /dev/null 2&>1 && echo clang || echo gcc
gcc

以下是一般情况:

$ which clang > /dev/null 2&>1; echo $?
1
$ which clang; echo $?
/usr/bin/clang
0

我如何重定向输出有问题。什么是正确的方式?

3 个答案:

答案 0 :(得分:13)

我认为你是以错误的方式重定向:

which clang > /dev/null 2&>1; echo $?

应该是

which clang > /dev/null 2>&1; echo $?

可能两种shell都允许使用前一种方法。在bash中,这不是正确的方式。 Bash会将其解释为:

which clang >/dev/null 2 &>1; echo $?

其中2被添加为参数。

您可以通过创建类似

的功能来验证这一点
e() { echo "$@" >e.log; }

并将其命名为:

e 1 >/dev/null 2&>/dev/null

你会在e.log中获得1 2

在bash中,如果你按照这样的命令调用它也会更简单:

which clang &>/dev/null; echo $?

而不是像which那样调用外部二进制文件,而是使用type -P。无需重定向stderr输出。

type -P clang >/dev/null; echo $?

答案 1 :(得分:3)

您正在使用zsh的&>运算符,该运算符重定向stderr和stdout。您使用它的方式表明您的意思是... > /dev/null 2>&1

我会这样做:

$ cc=$( type -P clang gcc othercc | head -n 1 )
$ echo $cc
/usr/bin/clang

答案 2 :(得分:0)

使用此:

which gcc >& /dev/null && echo gcc || echo clang

你也可以使用它:

[[ $(which gcc) ]] && echo gcc || echo clang # prints gcc
[[ $(which clang) ]] && echo gcc || echo clang # prints clang

这是有效的,因为[[ ]]空字符串是假的。