How to get loop exit status in bash

I know how to check the status of a previously executed command using $ ?, and we can make this status using the exit command. But for loops in bash, status 0 is always returned, and is there a way I can break a loop with some status.

#!/bin/bash while true do if [ -f "/test" ] ; then break ### Here I would like to exit with some status fi done echo $? ## Here I want to check the status. 
+6
source share
5 answers

The loop state is the state of the last command executed. You can use break to exit the loop, but if the break is successful, the loop state will be 0 . However, you can use the subshell and exit, rather than breaking. In other words:

 for i in foo bar; do echo $i; false; break; done; echo $? # The loop succeeds ( for i in foo bar; do echo $i; false; exit; done ); echo $? # The loop fails 

You can also put a loop in a function and return a value from it.

+19
source

Something like that?

 while true; do case $RANDOM in *0) exit 27 ;; esac done 

Or how is it?

 rc=0 for file in *; do grep fnord "$file" || rc=$? done exit $rc 

The real question is to decide if the loop exit code should succeed or fail if one iteration fails. There are scenarios where one makes more sense than the other, and the other where it does not clear at all.

+2
source

The bash manual says:

 while list-1; do list-2; done until list-1; do list-2; done [..]The exit status of the while and until commands is the exit status of the last command executed in list-2, or zero if none was executed.[..] 

The last command that runs inside the loop is break . And the value of the break output is 0 (see help break ).

This is why your program continues to exit from 0.

0
source

I think you should ask: how can I wait for a file or directory ( /test ) to be created by another process?

What you are doing so far is a full power survey. Your cycle will allocate up to 100% of the processing power of one core. The key word is a “survey” that is ethically flawed by the standards of computer scientists.

There are two means:

  • insert the sleep statement in your loop; advantage: very simple; Disadvantage: the delay will be an arbitrary compromise between CPU load and responsiveness. ("Arbitrary" is also ethically incorrect).
  • use a notification mechanism, for example inotify (see man inotify ); advantage: no CPU load, excellent responsiveness, no delays, no arbitrary constants in your code; Disadvantage: inotify is the kernel API - for this you need the code: inotify-tools or some C / Perl / Python code. Check out inotify and bash !
0
source

The gap built in for bash allows you to do what you do, it just breaks with a negative value and returns $ status? will be 1:

 while true do if [ -f "./test" ] ; then break -1 fi done echo $? ## You'll get 1 here.. 

Note that this is described in the help for the inline fault:

 help break 

break: break [n] Exit for, while or while loops.

Exits a FOR, WHILE, or UNTIL loop. If N is indicated, break N by looping.

Exit Status: The exit status is 0 if N is not greater than or equal to 1.

You can break out of n number of cycles or send a negative value for a break with a non-zero return, i.e. 1

I agree with @hagello, as one of the options sleeps and changes the loop:

 #!/bin/bash timeout=120 waittime=0 sleepinterval=3 until [[ -f "./test" || ($waittime -eq $timeout) ]] do $(sleep $sleepinterval) waittime=$((waittime + sleepinterval)) echo "waittime is $waittime" done if [ $waittime -lt $sleepinterval ]; then echo "file already exists" elif [ $waittime -lt $timeout ]; then echo "waited between $((waittime-3)) and $waittime seconds for this to finish..." else echo "operation timed out..." fi 
-1
source

All Articles