Tyler Pfaff
Tyler Pfaff

Reputation: 5032

Bash while loop, how to read input until a condition is false

I keep getting a run time error. I'm running this in a terminal on OSX. The error is,

test.sh: line 15: while[!false]: command not found
test.sh: line 16: syntax error near unexpected token `do'
test.sh: line 16: `do'

I just can't figure where I've got wrong syntactically as I'm new to writing bash scripts.

ipa build &
TASK_PID=$!
sleep 5
kill $TASK_PID

finished=false
declare -a schemes

echo "*****************************************************************************************"
echo "| View the list of available build configs above."
echo "| Enter the name of the build you want,one at a time."
echo "| Type \"done\" to finish entering scheme names"
echo "*****************************************************************************************"

while[!${finished}]
do
read input
  if[$input == "done"]
  then
      finished=true
  else
  schemes=("${schemes[@]}" $input)
  echo ${schemes[0]}
  fi
done

echo "Do you want a verbose build? (y/n)"
read verbose


echo "Building your selected schemes....."
ipa build -s ${schemes[0]}

Upvotes: 5

Views: 47802

Answers (3)

chepner
chepner

Reputation: 530922

true and false are not boolean keywords in bash; they are simply strings (and the names of commands; more on that in a moment). Even if you fix your syntax by supplying whitespace where necessary:

while ! [ "${finished}" ]; do
    ...
done

this loop will never run. Why? Whether finished has the value true or false, it is simply a non-empty string. This code will run the [ command (yes, it's a command, not syntax) and succeed because its argument is a non-empty string. The ! negates it, so that the condition for the while loop then always fails.

The most direct fix is to explicitly compare $finished to the string "true".

while [ "$finished" != "true" ]; do
   ...
done

I mentioned that true and false are also commands: true always succeeds, and false always fails. Usually, you do not want to do what I am about to suggest, but here it's OK because true and false are about as simple a pair of commands as you can imagine.

finished=false
while ! $finished; do
    ...
    # At some point
    finished=true
done

Here, we are letting $finished expand to the name of a command, which then executes and has its exit status negated by the !. As long as finished=false, the negated exit status is always 0 and the while loop will continue to run. Once you change the value of finished, the negated exit status will be 1 and the loop will exit.

Upvotes: 16

Emmet
Emmet

Reputation: 6391

Why not try something like this:

#!/bin/bash

list='Foo Bar Baz Quux Xyzzy QUIT'

select item in $list; do
    case $item in
    QUIT)
        break
        ;;
    *)
        echo "You picked '$item'!"
        ;;
    esac
done

Upvotes: 0

Amit
Amit

Reputation: 20456

Give space around brackets in test conditions

while [ ! ${finished} ]

&

if [ $input = "done" ]

Upvotes: 7

Related Questions