I'm wondering how the while loop evaluates its loop condition. In the man page it is written:
while list-1; do list-2; done
The while command continuously executes the list list-2 as long as the last command in the list list-1 returns an exit status of zero.
and
Lists
A list is a sequence of one or more pipelines separated by one of the operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or .
and
Pipelines
A pipeline is a sequence of one or more commands separated by one of the control operators | or |&. The format for a pipeline is:
[time [-p]] [ ! ] command [ [|⎪|&] command2 ... ]
This means:
while <single-command>; do <list>; done;
is valid syntax. The list is executed as long as <single-command>
returns 0
. If I run a while loop, like this, I get (obviously) errors:
$while aaa; do echo "foo"; done;
If 'aaa' is not a typo you can use command-not-found to lookup the package that contains it, like this:
cnf aaa
$while ; do echo "foo"; done;
Absolute path to '' is '/usr/sbin/', so running it may require superuser privileges (eg. root).
$while ""; do echo "foo"; done;
Absolute path to '' is '/usr/sbin/', so running it may require superuser privileges (eg. root).
To my surprise, using an unitialized variable bar
as <single-command>
, I run into an infinite loop:
$while $bar; do echo "foo"; done;
foo
foo
foo
...
This means, bar
gets parameter-expanded to an empty string(?), gets executed(?) and always returns 0. But why doesn't my second error-example work equivalently? Interestingly:
$while "$bar"; do echo "foo"; done;
Absolute path to '' is '/usr/sbin/', so running it may require superuser privileges (eg. root).
doesn't work. This is equivalent to my third error-example. $bar gets expanded to an empty string and the unescaped quotes remain.
So my question is: How does the shell(bash in my case) interpret the
$while $bar; do echo "foo"; done;
command which results in an endless-loop?
Update:
I found out that the null-command (does nothing, returns 0) isn't that hard to simulate. The null command corresponds to :
. So the non-terminating while-loop can be written equivalently as:
while :; do echo "foo"; done;
command_not_found_handle
function which emits the "Abolute path to..." message.bash
-specific (even though you tagged the question with bash), it happens underdash
as well. Usingset -x
, it seems that it treats it as an empty command. It's difficult to get the same kind of "empty command" effect using anything else (eveneval
won't do it).$bar
(withbar
unset) and trying to execute an empty string. Executing$bar
will be the same as just pressing return, while executing an empty string will result in a "command not found" (bash
) or " cannot execute [Is a directory]" (ksh93
). Doesn't quite explain it all though.:
command is much less interesting. That's an actual, non-null (builtin) command that is just liketrue
but spelled differently. Your discovery concerned a command with no name (not a blank name or length-0 name, none at all)