Question: I'm trying to get the exit code of the function that I'm repeatedly calling in the "condition" part of a Bash `while` loop:

```bash
while <function>; do 
    <stuff> 
done 

```

When this loop terminates due to an error, I need the exit code of `<function>`. Any thoughts on how I can get that?

Answer: 
You can capture the exit value from the condition and propagate that forward:

```
while rmdir FOO; ss=$?; [[ $ss -eq 0 ]]
do
    echo in loop
done
echo "out of loop with ?=$? but ss=$ss"

```

Output

```
rmdir: failed to remove 'FOO': No such file or directory
out of loop with ?=0 but ss=1

```

In this instance the exit status from `rmdir FOO` has been captured in the variable `ss` and is `1`. (Try replacing `rmdir FOO` with `( exit 4 )`. You'll find that `ss=4`.)

How does this work? Remember that the syntax is actually `while list-1; do list-2; done`, and not the much more usual expectation of `while command; do list; done`. The `list-1` can be a sequence of semicolon-separated commands, and the documentation states that the "*`while` command continuously executes the list `list-2` as long as the last command in the list `list-1` returns an exit status of zero.*"

As an alternative presentation of the messy-looking `while` condition, it is possible to assign a variable while inside an expression `(( ... ))`, and then to use the result. This gives the harder-to-read but more compact assign-and-test structure:

```
while rmdir FOO; ((! (ss=$?)))
do
    echo in loop
done
echo "out of loop with ?=$? but ss=$ss"

```

Alternatively you can use `while rmdir FOO; ! (( ss=$? ))`. These work because ((1)) evaluates arithmetically to 1, which is generally associated with true, and so the exit code of that evaluation is 0 (success). On the other hand, ((0)) evaluates arithmetically to 0, which is generally associated with false, and so the exit code of that evaluation is 1 (failure). This may seem confusing, as after all both evaluations `((.))` are "successful", but this is a hack to bring the value of arithmetic expressions representing true/false in line with bash's exit codes of success/failure, and make conditional expressions like `if ...; then ...; fi`, `while ...; do ...; done`, etc, work correctly, whether based on exit codes or arithmetic values.
One way to do this is to make the test explicitly instead of delegating it to `while`. So, the following should do:

```bash
err=0
while true
do
    <function>
    (( (err=$?) > 0 )) && break
    <stuff>
done
echo "$err"

```

At the beginning of the (a priori infinite) loop you would execute the condition command "manually" and store the exit code, check it, and break out of the loop if it is non-zero (indicating failure). Only if it was zero you execute the "actual" loop code.

The syntax can be "compacted" because (as noted by @roaima) you can have variable assignments inside the `(( ... ))` arithmetic test construct.