Reputation: 507
I realize the fact but I don't know why:
cat abc | echo $?
if abc
does not exist, but above command still return 0
. Anyone knows the theory about why?
Upvotes: 4
Views: 9036
Reputation:
The reason why it must be this way is that a pipeline is made of processes running simultaneously. cat
's exit code can't possibly be passed to echo
as an argument because arguments are set when the command begins running, and echo
begins running before cat
has finished.
echo
doesn't take input from stdin, so echo
on the right side of a pipe character is always a mistake.
UPDATE:
Since it is now clear that you are asking about a real problem, not just misunderstanding what you saw, I tried it myself. I get what I think is the correct result (1) from a majority of shells I tried (dash, zsh, pdksh, posh, and bash 4.2.37) but 0 from bash 4.1.10 and ksh (Version JM 93u+ 2012-02-29).
I assume the change in bash's behavior between versions is intentional, and the 4.1.x behavior is considered a bug. You'd probably find it in the changelog if you looked hard enough. Don't know about ksh.
csh and tcsh (with $status
in place of $?
) also say 0, but I bet nobody cares about that.
People with bigger shell collections are invited to test:
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
Upvotes: 11
Reputation: 289495
It does not have anything to do with cat abc
, but with the previous command you executed. So the code you get when doing cat abc | echo $?
is telling if the previous command in your history was successful or not.
From man bash
:
Special Parameters
? - Expands to the exit status of the most recently executed foreground pipeline.
So when you do:
cat abc | echo $?
The echo $?
refers to the previous command you used, not cat abc
.
$ cat a
hello
$ echo $?
0
$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ echo $?
1
So
$ cat a
$ cat a | echo $?
0
$ cat aldsjfaslkdfj
cat: aldsjfaslkdfj: No such file or directory
$ cat a | echo $?
1
Upvotes: 7
Reputation: 1500
You pipe the output from 'cat abc' to 'echo $?' which is not what you want. You want to echo the exit code of 'cat'
cat abc; echo $?
is what you want. Or simply write it in two lines if you can.
Upvotes: 0
Reputation: 983
echo $? will give output of previous command which you have executed before not output of piped command. So, you will always get echo $? as 0 even if command failed before pipe.
Upvotes: 0