Home > Software design >  Why is my BASH compiler skipping over my code?
Why is my BASH compiler skipping over my code?

Time:06-20

I wrote a for loop to get the number of tools that haven't been installed. This is my code:

#!/bin/bash

DIALOG_INSTALLED=$(which dialog)
BREW_INSTALLED=$(which brew)
TELNET_INSTALLED=$(which telnet)

UNINSTALLED_TOOLS=0

for installed_for in $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED; do
    if [[ -z $installed_for ]]; then
        let "$UNINSTALLED_TOOLS =1"
    fi
done

echo $UNINSTALLED_TOOLS

My problem is that when I go to run the code, $UNINSTALLED_TOOLS is still equal to 0. To find the root of the issue, $UNINSTALLED_TOOLS=3 before and after the for loop. Both of these adjustments changed the final value of $UNINSTALLED_TOOLS to 3. Now I know that the issue lies within the for loop. It's as if the code is skipping over the for loop. I don't get any syntax errors so I'm very confused.

Any help is appreciated.

CodePudding user response:

for installed_for in $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED; do

This isn't a loop over 3 elements; it's a loop over however many words the variables $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED expand to. So for instance if you had /usr/bin/dialog, /bin/telnet, but brew was uninstalled, then the for will be a loop over 2 elements, just as if you had typed

for installed_for in /usr/bin/dialog  /bin/telnet; do

In particular, [[ -z $installed_for ]] will never be true.

You probably want to quote them, so that if any of them is empty, the for loop still iterates over it as an empty string:

for installed_for in "$DIALOG_INSTALLED" "$BREW_INSTALLED" "$TELNET_INSTALLED"; do

Also, let "$UNINSTALLED_TOOLS =1" is wrong. It expands $UNINSTALLED_TOOLS before evaluating the arithmetic, so it becomes something like let 0 =1 which is invalid. It should instead be let "UNINSTALLED_TOOLS =1".

CodePudding user response:

Assume dialog is not found. After variable substitution, you get:

for installed_for in /usr/local/bin/brew /usr/local/bin/telnet; do

So $installed_for never has an opportunity to be an empty string. Once you make for loop with the empty string, your let is incorrect, too, since after the substitution you have

let 0 =1

which makes no sense. So:

DIALOG_INSTALLED=$(which dialog)
BREW_INSTALLED=$(which brew)
TELNET_INSTALLED=$(which telnet)

INSTALLED_ARRAY=("$DIALOG_INSTALLED" "$BREW_INSTALLED" "$TELNET_INSTALLED")
UNINSTALLED_TOOLS=0

for installed_for in "${INSTALLED_ARRAY[@]}"; do
    if [[ -z $installed_for ]]; then
        let UNINSTALLED_TOOLS =1
    fi
done
echo "$UNINSTALLED_TOOLS"
  • Related