Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash loop until a certain command stops failing

Tags:

bash

shell

I would like to write a loop in bash which executes until a certain command stops failing (returning non-zero exit code), like so:

while ! my_command; do
    # do something
done

But inside this loop I need to check which exit code my_command returned, so I tried this:

while ! my_command; do
    if [ $? -eq 5 ]; then
        echo "Error was 5"
    else
        echo "Error was not 5"
    fi
    # potentially, other code follows...
done

But then the special variable ? becomes 0 inside the loop body. The obvious solution is:

while true; do
    my_command
    EC=$?
    if [ $EC -eq 0 ]; then
        break
    fi
    some_code_dependent_on_exit_code $EC
done

How can I check the exit code of my_command (called in loop header) inside loop body without rewriting this example using a while true loop with a break condition as shown above?

like image 886
Michał Trybus Avatar asked Feb 15 '16 14:02

Michał Trybus


People also ask

How do you stop an infinite loop in Git bash?

Infinite while Loop You can also use the true built-in or any other statement that always returns true. The while loop above will run indefinitely. You can terminate the loop by pressing CTRL+C .

Does bash wait for command to finish?

The bash wait command is a Shell command that waits for background running processes to complete and returns the exit status. Unlike the sleep command, which waits for a specified time, the wait command waits for all or specific background tasks to finish.

How do you break out of a for loop in bash?

Using break Inside for Loops To add a conditional statement and exit a for loop early, use a break statement. The following code shows an example of using a break within a for loop: #!/bin/bash for i in {1.. 10} do if [[ $i == '2' ]] then echo "Number $i!" break fi echo "$i" done echo "Done!"

How do I stop a shell script from failing the command?

Exit When Any Command Fails This can actually be done with a single line using the set builtin command with the -e option. Putting this at the top of a bash script will cause the script to exit if any commands return a non-zero exit code.


2 Answers

In addition to the well-known while loop, POSIX provides an until loop that eliminates the need to negate the exit status of my_command.

# To demonstrate
my_command () { read number; return $number; }

until my_command; do
    if [ $? -eq 5 ]; then
        echo "Error was 5"
    else
        echo "Error was not 5"
    fi
    # potentially, other code follows...
done
like image 153
chepner Avatar answered Sep 18 '22 16:09

chepner


If true command hurt your sensibility, you could write:

while my_command ; ret=$? ; [ $ret -ne 0 ];do
    echo do something with $ret
  done

This could be simplified:

while my_command ; ((ret=$?)) ;do
    echo do something with $ret
  done

But if you don't need ResultCode, you could simply:

while my_command ; [ $? -ne 0 ];do
    echo Loop on my_command
  done

or

while my_command ; (($?)) ;do
    echo Loop on my_command
  done

And maybe, why not?

while ! my_command ;do
    echo Loop on my_command
  done

But from there you could better use until as chepner suggest

like image 36
F. Hauri Avatar answered Sep 21 '22 16:09

F. Hauri