Reputation: 1521
I am trying to evaluate a boolean variable in Bash scripting, but it always return false.
Here is the code:
DEVICE_FOUND=false
tmp=`adb devices | tail -n+2 | awk '{print $1}'`
echo "$tmp" | while read line
do
if [ "$DEVICE_ID" = "$line" ]
then
echo "Found a device"
DEVICE_FOUND=true
fi
done
if ! $DEVICE_FOUND
then
echo "ERROR: The device "$DEVICE_ID" is not connected"
exit
fi
Whether or not "Found a device" gets executed or not, I always go into the if statement. When DEVICE_FOUND=true, it should not go in the last if but it does.
I do not understand why is that.
Does anyone please know?
Thank you very much.
Upvotes: 3
Views: 3448
Reputation: 125838
The problem isn't the boolean, it's that the while loop is in a pipeline, and therefore executes in a subshell. Changing DEVICE_FOUND in the subshell has no effect on DEVICE_FOUND in the main shell, it just stays false. If you're using bash (i.e. if the shebang at the beginning of the script is #!/bin/bash
, not #!/bin/sh
), there are a couple of ways to eliminate the pipe:
while read line
do
if [ "$DEVICE_ID" = "$line" ]
then
echo "Found a device"
DEVICE_FOUND=true
fi
done < <(echo "$tmp")
or:
while read line
do
if [ "$DEVICE_ID" = "$line" ]
then
echo "Found a device"
DEVICE_FOUND=true
fi
done <<<"$tmp"
But in this particular case there's a better way (provided $DEVICE_ID
doesn't have any regex metacharacters):
if echo "$tmp" | grep -q "^$DEVICE_ID\$"; then
echo "Found a device"
else
echo "ERROR: The device "$DEVICE_ID" is not connected"
exit
fi
Upvotes: 3
Reputation: 14970
There is no boolean type in bash (and any POSIX-compliant shell). What effectively happens is that you are running the true
(exits with success status, not necessarily 0
) or false
(exits with failure status, not necessarily not 0
) external commands in the if
statement. The if
statement executes the second list if the first list evaluates to 0
. You might have encountered a system where neither the true
or false
commands are available, or where they work differently than expected. Use "integer" values (all values are internally strings) or empty/non-empty string values instead.
On a side note, consider this:
adb devices | tail -n +2 | awk '{print $1}' | while read …
do
…
done
Upvotes: 0
Reputation: 241918
That's because you are setting the true value after the |
, i.e. in a subshell. Variable values from a subshell do not propagate back to the parent shell. Get rid of the subshell:
while read line
do
...
done <<< "$tmp"
Upvotes: 7
Reputation: 2065
Bash lacks boolean variables. Hence DEVICE_FOUND=false
assigns the string false
to $DEVICE_FOUND
.
You can get the usual boolean flag functionality by using the "empty variable" condition as as your "false", and "nonempty variable" as your "true" (or viceversa if you want), or otherwise check for arbitrary values. Example:
DEVICE_FOUND=""
tmp=`adb devices | tail -n+2 | awk '{print $1}'`
echo "$tmp" | while read line
do
if [ "$DEVICE_ID" = "$line" ]
then
echo "Found a device"
DEVICE_FOUND=true
fi
done
if [ ! "$DEVICE_FOUND" ]
then
echo "ERROR: The device "$DEVICE_ID" is not connected"
exit
fi
Upvotes: 1