31

There is the well known while condition; do ...; done loop, but is there a do... while style loop that guarantees at least one execution of the block?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Shawn J. Goff
  • 45,338
  • 25
  • 134
  • 145
  • Many thanks Shawn, I didn't expect the answer to become the selected answer so fast. So: thanks for the selection. –  Dec 14 '15 at 01:36

2 Answers2

34

A very versatile version of a do ... while has this structure:

while 
      Commands ...
do :; done

An example is:

#i=16
while
      echo "this command is executed at least once $i"
      : ${start=$i}              # capture the starting value of i
      # some other commands      # needed for the loop
      (( ++i < 20 ))             # Place the loop ending test here.
do :; done
echo "Final value of $i///$start"
echo "The loop was executed $(( i - start )) times "

As it is (no value set for i) the loop executes 20 times.
UN-Commenting the line that sets i to 16 i=16, the loop is executed 4 times.
For i=16, i=17, i=18 and i=19.

If i is set to (let's say 26) at the same point (the start), the commands still get executed the first time (until the loop break command is tested).

The test for a while should be truthy (exit status of 0).
The test should be reversed for an until loop, i.e.: be falsy (exit status not 0).

A POSIX version needs several elements changed to work:

i=16
while
       echo "this command is executed at least once $i"
       : ${start=$i}              # capture the starting value of i
       # some other commands      # needed for the loop
       i="$((i+1))"               # increment the variable of the loop.
       [ "$i" -lt 20 ]            # test the limit of the loop.
do :;  done
echo "Final value of $i///$start"
echo "The loop was executed $(( i - start )) times "

./script.sh
this command is executed at least once 16
this command is executed at least once 17
this command is executed at least once 18
this command is executed at least once 19
Final value of 20///16
The loop was executed 4 times 
  • 2
    Bare in mind that if you use `set -e` anything failing inside the while condition block isn't going to stop execution: e.g. `set -e; while nonexistentcmd; true; do echo "SHiiiiit"; exit 3; done` -> shit happens. So, if you use this you got to be really careful with error handling i.e. chain all commands with `&&`! – Timo Mar 05 '18 at 08:59
28

There isn't a do...while or do...until loop, but the same thing can be accomplished like this:

while true; do
  ...
  condition || break
done

for until:

until false; do
  ...
  condition && break
done
Shawn J. Goff
  • 45,338
  • 25
  • 134
  • 145
  • You can use either of the break lines with either of the loops - while true or until false just mean 'forever'. I understand it kinda preserves the while-ness or until-ness to have the condition happy-exit or sad-exit. – android.weasel Dec 04 '15 at 17:26