akshaybetala
akshaybetala

Reputation: 317

How to get the exit status of second last command?

I want to run 2 commands and output the exit status of the first command. And all this, I want to do it in a single line of command. Something like this

cmd1; cmd2 && echo $?-1

It should output the exit status of cmd1.

Upvotes: 8

Views: 4472

Answers (3)

Luke Schoen
Luke Schoen

Reputation: 4543

If you have two commands as follows where you are checking the version of the first command to see if you have the correct version of the command installed:

#!/usr/bin/env bash

set -e

cmd1="my_command version"
cmd2="sleep 1"
exit_code=$(${cmd1}; status=$?; ${cmd2} && echo $status)
printf "_${exit_code}_"

if [[ "_${exit_code}_" == "_0_" && "$(my_command version)" =~ " 1." ]]; then
   my_command
fi

The output could be the following if version was a valid option or command of my_command, where my_command 1.0.0 is the output of my_command version and 0 is the exit code at the end. Note that I have used surrounded the value with _ just to make it clear:

_my_command 1.0.0
0_

And that would not satisfy the first condition of the if statement.

But the output could be the following if the version of my_command that was currently installed was a different version that only supported use of the option --version and so use of my_command version was invalid:

_1_

To resolve that issue I simply got the exit code from the last character with last_char=${exit_code: -1} and changed the first condition of the if statement to be "_${last_char}_" == "_0_" instead

#!/usr/bin/env bash

set -e

cmd1="my_command version"
cmd2="sleep 1"
exit_code=$(${cmd1}; status=$?; ${cmd2} && echo $status)
last_char=${exit_code: -1}
printf "_${last_char}_"

if [[ "_${last_char}_" == "_0_" && "$(my_command version)" =~ " 1." ]]; then
   my_command
fi

Upvotes: 0

RaphaMex
RaphaMex

Reputation: 2839

cmd1; status=$?; cmd2 && echo $status

Upvotes: 3

Charles Duffy
Charles Duffy

Reputation: 295815

Like any other global variable that has its status updated over time (ie. errno in C), if you want to refer to an old value, you need to store it ahead-of-time.

cmd1; cmd1_retval=$?; cmd2 && echo "$cmd1_retval"

The place where this is different, by the way, is in a pipeline:

cmd1 | cmd2 | cmd3
echo "${PIPESTATUS[$(( ${#PIPESTATUS[@]} - 2 ))]}"

That's because in a pipeline, all components run at once, and by default the exit status is that of the last one. In bash, however, the exit status of all components is stored in the PIPESTATUS array; ${#PIPESTATUS[@]} takes the length of this array, and subtracting two from it (one because of the difference between 0- and 1-based indexing, and one to get from the last item to the second-to-last item) gets the second-to-last item in the preceding pipeline.

Upvotes: 11

Related Questions