I used to write my scripts like this:

while [ $? -ne 0 ] ; do
    sleep 1

It always irked me that I have to write some_command twice. Can I put it inside the loop test section somehow?


You could use some_command as your test condition.

while ! some_command; do sleep 1; done

The condition will remain true as long as some_command exits with an error.

Or a more verbose way if you want to do additional checks:

while ! some_command
    # add more if desired
    sleep 1
  • This looks better than mine, even though it is a one-liner ;-) – Anthon Dec 22 '14 at 15:46
  • The OP might want to split it into several lines should he need to execute several commands upon failure, though :) – John WH Smith Dec 22 '14 at 15:50
  • No reason why you can't line-break it at the semi-colons to make it multi-line. – Mark Stewart Dec 22 '14 at 16:03
  • 1
    ... or write while ! some_command; do several; commands; sleep 1; done – ignis Dec 23 '14 at 18:04

This is what the until loop is for:

until some_command
do    sleep 1

It is the logical negation of a while loop.

The spec says:

The until Loop

  • The until loop shall continuously execute one compound-list as long as another compound-list has a non-zero exit status.

  • The format of the until loop is as follows:

    until compound-list-1
    do    compound-list-2
  • The compound-list-1 shall be executed, and if it has a zero exit status, the until command completes. Otherwise, the compound-list-2 shall be executed, and the process repeats.

You can just do:

while [ $? -ne 0 ] ; do
   sleep 1

this has the disadvantage though that it always sleeps one second first

If you want to be able to exit on any of a number of commands to exit with 0 you can do :

while true; do
  if [ some_command ] ; then break ; fi
  if [ some_other_command ] ; then break ; fi
  sleep 1

which of course also works for just some_command

  • 5
    The second example shouldn't include [ and ] around the commands. – nyuszika7h Dec 22 '14 at 23:14

Neither while ! ... nor until ... works on the systems that froze their shell environment prior to POSIX.1-2001. This, however, does.

while :; do
    if some command; then
    sleep 1

If you don't need total portability, why are you writing a shell script? Perl is more likely to be available than Bash.

sleep 1 while 0 != system qw(some command);

(As above, the sleep is only executed if the command fails.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.