There seems to be some misunderstanding here about the Bash builtin true
, and more specifically, about how Bash expands and interprets expressions inside brackets.
The code in miku's answer has absolutely nothing to do with the Bash builtin true
, nor /bin/true
, nor any other flavor of the true
command. In this case, true
is nothing more than a simple character string, and no call to the true
command/builtin is ever made, neither by the variable assignment, nor by the evaluation of the conditional expression.
The following code is functionally identical to the code in the miku's answer:
the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
echo 'Be careful not to fall off!'
fi
The only difference here is that the four characters being compared are 'y', 'e', 'a', and 'h' instead of 't', 'r', 'u', and 'e'. That's it. There's no attempt made to call a command or builtin named yeah
, nor is there (in miku's example) any sort of special handling going on when Bash parses the token true
. It's just a string, and a completely arbitrary one at that.
Update (2014-02-19): After following the link in miku's answer, now I see where some of the confusion is coming from. Miku's answer uses single brackets, but the code snippet he links to does not use brackets. It's just:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Be careful not to fall off!'
fi
Both code snippets will behave the same way, but the brackets completely change what's going on under the hood.
Here's what Bash is doing in each case:
No brackets:
- Expand the variable
$the_world_is_flat
to the string "true"
.
- Attempt to parse the string
"true"
as a command.
- Find and run the
true
command (either a builtin or /bin/true
, depending on the Bash version).
- Compare the exit code of the
true
command (which is always 0) with 0. Recall that in most shells, an exit code of 0 indicates success and anything else indicates failure.
- Since the exit code was 0 (success), execute the
if
statement's then
clause
Brackets:
- Expand the variable
$the_world_is_flat
to the string "true"
.
- Parse the now-fully-expanded conditional expression, which is of the form
string1 = string2
. The =
operator is bash's string comparison operator. So...
- Do a string comparison on
"true"
and "true"
.
- Yep, the two strings were the same, so the value of the conditional is true.
- Execute the
if
statement's then
clause.
The no-brackets code works, because the true
command returns an exit code of 0, which indicates success. The bracketed code works, because the value of $the_world_is_flat
is identical to the string literal true
on the right side of the =
.
Just to drive the point home, consider the following two snippets of code:
This code (if run with root privileges) will reboot your computer:
var=reboot
if $var; then
echo 'Muahahaha! You are going down!'
fi
This code just prints "Nice try." The reboot command is not called.
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
Update (2014-04-14) To answer the question in the comments regarding the difference between =
and ==
: AFAIK, there is no difference. The ==
operator is a Bash-specific synonym for =
, and as far as I've seen, they work exactly the same in all contexts.
Note, however, that I'm specifically talking about the =
and ==
string comparison operators used in either [ ]
or [[ ]]
tests. I'm not suggesting that =
and ==
are interchangeable everywhere in bash.
For example, you obviously can't do variable assignment with ==
, such as var=="foo"
(well technically you can do this, but the value of var
will be "=foo"
, because Bash isn't seeing an ==
operator here, it's seeing an =
(assignment) operator, followed by the literal value ="foo"
, which just becomes "=foo"
).
Also, although =
and ==
are interchangeable, you should keep in mind that how those tests work does depend on whether you're using it inside [ ]
or [[ ]]
, and also on whether or not the operands are quoted. You can read more about that in Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scroll down to the discussion of =
and ==
).