Open rugk opened 7 years ago
Variables don't have "types" so detecting when a variable should be considered a "boolean" is problematic; "false" is a perfectly good string value that has other uses.
Of course, the real problem is the inappropriate pervasive use of [ ... ]
(the string-test command) in conjunction with if ... then
when
they are actually separate constructs and do not have to be used
together.
As for the appropriate idiom, just writing
var=false
if $var ; then ...
works fine. As does
readonly true=1 false= # necessary preamble, just once
...
var=false
if ((var)) ; then ...
And just for the record, your suggested fix would always result in "true", because "=true" is still a non-empty string.
On 5 January 2017 at 08:09, rugk notifications@github.com wrote:
For new checks and feature suggestions
- shellcheck.net (i.e. the latest commit) currently gives no useful warnings about this
- I searched through https://github.com/koalaman/shellcheck/issues and didn't find anything related
Here's a snippet or screenshot that shows the problem:
Many beginners may be familiar with other languages where you can just do if ( false ) { #code here not executed } and thus e.g. use a variable if ( $featureIsEnabled ) { #execute awesome feature } to conditionally do or not do things. These users may expect that the code is not executed when $featureIsEnabled is e.g. set to false or (in case of variable casting) to 0.
However Linux/POSIX shells seem to do it differently and threat everything as true (even a boolean "false") and only evaluate to false when nothing (an empty string) is given. The example below shows this in code form.
!/bin/sh
vars="0 1 true false" for var in $vars; do
echo "testing $var"
if [ "$var" ]; then echo "var $var is true" fi if [ ! "$var" ]; then echo "var $var is false" fidone
test boolean: true
myBoolOption=trueif [ "$myBoolOption" ]; then echo "var
is true"fiif [ ! "$myBoolOption" ]; then echo "var is false"fi test boolean: false
myBoolOption=falseif [ "$myBoolOption" ]; then echo "var
is true"fiif [ ! "$myBoolOption" ]; then echo "var is false"fi test empty string
emptyString=""if [ "$emptyString" ]; then echo "var <> is true"fiif [ ! "$emptyString" ]; then echo "var <> is false"fi
Output:
$ ./test.shvar 0 is truevar 1 is truevar true is truevar false is truevar
is truevar is truevar <> is false Shellcheck does not complain about this code at all.
So for beginners things such as var false is true can be a horrible error cause.
That's why I'd like to see a message from shellcheck in this cases as I think it could help many devs to prevent unnecessary debugging of such an issue, which is not apparent.
I don't know exactly when/how it should complain, but maybe it could show a warning for if [ "$myBoolOption" ]; then and e.g. suggest to use if [ "$myBoolOption"=true ]; then if it detects that $myBoolOption is a boolean or a 0/1 value or so.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/koalaman/shellcheck/issues/816, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMChXl61-Ryg6KzTK_hCUDrnXczw-xaks5rPAqJgaJpZM4LbEdH .
Nice, indeed a good idea to just use if $var ; then
. Maybe suggest this instead.
I would also like some sort of shellcheck rule that would point this potential gotcha out. Suggesting if $var ; then
would be good, or if [ "$var" = "true" ] ; then
(or if [[ "$var" == "true" ]] ; then
. (Depending on the context, sometimes I prefer the shorter version; other times I prefer to use the strings "true" and "false" but make it more obvious that they are just strings.
@rugk Please don't write:
if $var ; then
It's not totally "wrong", but it has problems.
var
contains space, tab, or newline, then it will be subject to word splitting;*
, ?
, or [...]
, then it will subject to filename globbing. The speed of the latter will depend on how many files are in the current directory; if you're in a network filesystem, that can take many seconds.var
as a command and runs it; this would be bad if it contained, say, rm -rf /*
Please use this instead:
if (( var )) ; then
(It's not perfect, but it's much faster, and (in newer shells) more secure; it's certainly no worse, even in older shells.)
Is that POSIX compatible though? Anyway one needs to come up with a proper suggestion of what is actually the best practise/recommend way and then a shellcheck rule could be implemented.
For new checks and feature suggestions
Here's a snippet or screenshot that shows the problem:
Many beginners may be familiar with other languages where you can just do
if ( false ) { #code here not executed }
and thus e.g. use a variableif ( $featureIsEnabled ) { #execute awesome feature }
to conditionally do or not do things. These users may expect that the code is not executed when$featureIsEnabled
is e.g. set tofalse
or (in case of variable casting) to0
.However Linux/POSIX shells seem to do it differently and threat everything as
true
(even a boolean "false") and only evaluate to false when nothing (an empty string) is given. The example below shows this in code form.Output:
Shellcheck does not complain about this code at all.
So for beginners things such as
var false is true
can be a horrible error cause.That's why I'd like to see a message from shellcheck in this cases as I think it could help many devs to prevent unnecessary debugging of such an issue, which is not apparent.
I don't know exactly when/how it should complain, but maybe it could show a warning for
if [ "$myBoolOption" ]; then
and e.g. suggest to useif [ "$myBoolOption"=true ]; then
if it detects that$myBoolOption
is a boolean or a 0/1 value or so.