为什么在管道总是返回" 0"之后回显返回值($?)

时间:2014-04-02 12:10:00

标签: shell echo pipeline

我意识到这个事实,但我不知道为什么:

cat abc | echo $?

如果abc不存在,但上面的命令仍会返回0。有谁知道关于为什么的理论?

4 个答案:

答案 0 :(得分:9)

必须这种方式的原因是管道由同时运行的进程组成。 cat的退出代码不能作为参数传递给echo,因为参数在命令开始运行时设置,echocat之前开始运行1}}已经完成。

echo没有从标准输入中获取输入,因此管道字符右侧的echo始终是错误的。

<强>更新

既然现在很清楚你是在问一个真正的问题,而不仅仅是误解了你看到的东西,我自己也试过了。我从我尝试过的大多数shell(dash,zsh,pdksh,posh和bash 4.2.37)中得到了我认为正确的结果(1),但是从bash 4.1.10和ksh(版本JM 93u + 2012-02)得到0 -29)。

我认为版本之间bash行为的变化是有意的,4.1.x行为被认为是一个bug。如果你看起来足够努力,你可能会在更新日志中找到它。不知道ksh。

csh和tcsh(用$status代替$?)也说0,但我打赌没有人关心这个。

邀请拥有更多shell集合的人进行测试:

for sh in /bin/sh /bin/ksh /bin/bash /bin/zsh ...insert more shells here...; do
  echo -n "$sh "
  $sh -c 'false;true|echo $?'
done

答案 1 :(得分:4)

它与cat abc没有任何关系,但是您执行了上一个命令。因此,在执行cat abc | echo $?时获得的代码告诉您历史记录中的上一个命令是否成功。

来自man bash

  

特殊参数

     

- 扩展到最近执行的前台管道的退出状态。

所以当你这样做时:

cat abc | echo $?

echo $?是指您使用的上一个命令,而不是cat abc

实施例

$ cat a
hello
$ echo $?
0

$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ echo $?
1

所以

$ cat a
$ cat a | echo $?
0

$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ cat a | echo $?
1

答案 2 :(得分:1)

您将'cat abc'的输出传输到'echo $?'这不是你想要的。 您想要回显'cat'的退出代码

cat abc; echo $?

是你想要的。或者,如果可以,只需将其写成两行。

答案 3 :(得分:0)

回声$?将在不输出管道命令之前给出您执行的上一个命令的输出。那么,你总会得到回声$?即使命令在管道之前失败,也为0。