What does "while :;" mean?
The syntax is:
while
first list of commands
do
second list of commands
done
which runs the second list of commands in a loop as long as the first list of commands (so the last run in that list) is successful.
In that first list of commands, you can use the [
command to do various kinds of tests, or you can use the :
null command that does nothing and returns success, or any other command.
while :; do cmd; done
Runs cmd
over and over forever as :
always returns success. That's the forever loop. You could use the true
command instead to make it more legible:
while true; do cmd; done
People used to prefer :
as :
was always builtin while true
was not (a long time ago; most shells have true
builtin nowadays)¹.
Other variants you might see:
while [ 1 ]; do cmd; done
Above, we're calling the [
command to test whether the "1" string is non-empty (so always true as well)
while ((1)); do cmd; done
Using the Korn/bash/zsh ((...))
syntax to mimic the while(1) { ...; }
of C.
Or more convoluted ones like until false; do cmd; done
, until ! true
...
Those are sometimes aliased like:
alias forever='while :; do'
So you can do something like:
forever cmd; done
Few people realise that the condition is a list of commands. For instance, you see people writing:
while :; do
cmd1
cmd2 || break
cmd3
done
When they could have written:
while
cmd1
cmd2
do
cmd3
done
It does make sense for it to be a list as you often want to do things like while cmd1 && cmd2; do...; done
which are command lists as well.
In any case, note that [
is a command like any other (though it's built-in in modern Bourne-like shells), it doesn't have to be used solely in the if
/while
/until
condition lists, and those condition lists don't have to use that command more than any other command.
¹ :
is also shorter and accepts arguments (which it ignores). While the behaviour of true
or false
is unspecified if you pass it any argument. So one may do for instance:
while : you wait; do
something
done
But, the behaviour of:
until false is true; do
something
done
is unspecified (though it would work in most shell/false
implementations).
while :
is an infinite loop. :
just does nothing (successfully).
So if you want your shell to hang forever doing nothing, you can write it as
while :
do
:
done
Or in a single line with ;
instead of newlines: while :; do :; done
while :
is usually used if you want to do something repeatedly without a special condition attached. You might use continue
, break
statements within the loop to control it or to move the condition to the end of the loop like a do ... while
construct.
howsoever, the statement after while has to be either TRUE or FALSE.
No, the command in the condition part can be any command(*) . All shell commands have some return value, and the while
loop (as well as the if
conditional) take return values of zero as "true", and all others as "false". (* or a list of several commands, the last one counts)
As for :
, Bash's manual tells clearly what the return status of that is:
: [arguments]
Do nothing beyond expanding arguments and performing redirections. The return status is zero.
The help
builtin is even more clear:
$ help :
[...]
No effect; the command does nothing
Exit Status:
Always succeeds.