a bash pipe command exit code rule

0

I was writing a simple script that checks the output of a command that if it displays a certain keyword. To see if it works, I was checking the command from the bash command line.

   $ ls | grep -q foo
   $ echo $?

It displayed 1 or 0 depends on the command output and a grep parameter as I expected.

I get little lazy to type the command again, so I added | echo $? at the end of the command line.

    $ ls | grep -q foo | echo $?

Then regardless the command output, it always returns 0, even if the first part returns 1.

I guess this is normal behavior but I'd like to know why bash works this way.

Chihaya

Posted 2017-01-05T16:56:44.400

Reputation: 51

Answers

1

This is because the pipe takes the stdout and pipes it to the next command, what you want instead is the semicolon.

ls | grep -q foo; echo $?

This finished the ls and grep commands and then executes the echo command.

ojs

Posted 2017-01-05T16:56:44.400

Reputation: 890

2

The special variable $? expands to the exit status of the most recently executed foreground pipeline. In your example, the | echo $? is the most recently executed foreground pipeline, at that point the exit status of the command before the last | is no longer accessible via $?.

On a related note, you can use the exit code directly in conditional statements, for example:

if ls | grep -q foo; then echo success, there is foo; fi

Or, if you want to execute something on success, you could chain the next command using &&:

ls | grep -q foo && echo success

janos

Posted 2017-01-05T16:56:44.400

Reputation: 2 449