0

I am trying to figure out how the while loop logic works in bash.

If I have 4 instructions; that are in a loop, they will be executed n times, following the conditions set in the loop.

Although; is the loop aware of the return code for each of these commands?

Ideally you could write a shell script with a while loop where you check for exit code of each command, and do it again if any of the command return an error. Is this logic possible in bash or the loop is not aware of the return code of each command, and see the block between the do-done, as one?

EDIT:

example:

a=2
b="test"

while [ "$?" != 0 ]
do
   ls $b
   cd $b
   grep "2.txt" | mv 2.txt $a.txt
   ls $b
done

This simplified example is basically checking for a dir, cd into it, find a file with a specific name and rename it.

When I run this loop, if any of these commands return code is not 0, the loop should start all over, until all the commands return 0 and then the loop exit.

Is this actually true or the whole block of commands is handled as single entity, so if the last command return 0 it will exit?

4
  • Can you show example code and comment on the parts you aren't sure about? Commented Sep 9, 2015 at 18:38
  • Hi, I did add an example to show conceptually what I am not sure about. Thanks Commented Sep 9, 2015 at 18:45
  • Your test will use the most recent value of $?, which is set by the last statement prior to the while loop for the first iteration, and by the last statement of the body for subsequent iterations. Commented Sep 9, 2015 at 18:50
  • Actually no; this is why I got confused; I was expecting the loop to read each return code for each command, which is not true Commented Sep 9, 2015 at 19:07

2 Answers 2

2

The while command only checks the exit status of the condition statement immediately following it. It doesn't check the status of the statements inside the loop.

You can use an if statement inside the loop to break out of the loop.

while something
do
    command1
    if ! command2
    then break
    fi
    command3
done

This will loop as long as something is successful, but stop if command2 fails.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Barmar, so it is as I thought; it is not aware of each single command in the loop. So if I have N commands, I shall put an if on each command to check if the return code is not 0?
You can write && after each command except the last one and check the result after the last command. Or maybe better write || break after each command.
2

Perhaps: use an infinite loop, and join all the commands with && with break at the end

while true
do
   ls $b &&
   cd $b &&
   grep "2.txt" | mv 2.txt $a.txt &&
   ls $b &&
   break
done

Note while ...; do ...; done not while ...; do ...; loop

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.