Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

msjones

macrumors 6502
Original poster
Oct 18, 2007
429
4
Nottinghamshire, UK
Evening all,

I am having a little fun with some shell scripting but I am stuck creating a loop. Hopefully someone can help. Here is my script:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

if [ $COUNT -lt 140 ]
 then
  while true; do
  echo "$FORTUNE" && exit
 done
fi

As you can see if $FORTUNE is less than 140 characters it will echo the text and then close. If $FORTUNE is greater than 140 it will just close. What I want it to do is if its greater than 140 to re-run again until its less than 140, echo and then exit.

Hope this makes sense?
 
As you can see if $FORTUNE is less than 140 characters it will echo the text and then close. If $FORTUNE is greater than 140 it will just close. What I want it to do is if its greater than 140 to re-run again until its less than 140, echo and then exit.

According to that description, the if must be inside a loop, not outside it. So structurally you need this:
Code:
while ..
  ..
  if ..
    ...
  fi
  ..
done
but your posted code has this:
Code:
if ..
  while ..
    ..
  done
fi
 
OK So ive changed to this:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

while true; do
 if [ $COUNT -lt 140 ]
  then
   echo "$FORTUNE" && exit
 fi
done

This will post if $FORTUNE is less than 140 but if its greater than 140 it just hangs?
 
OK So ive changed to this:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

while true; do
 if [ $COUNT -lt 140 ]
  then
   echo "$FORTUNE" && exit
 fi
done

This will post if $FORTUNE is less than 140 but if its greater than 140 it just hangs?

Thats because you have no exit condition if the count is not less than 140...you have an infinite loop.
 
This is where I am at currently:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

while [ $COUNT -lt 140 ]
 do
   echo "$FORTUNE"
   exit 0
done

This works fine, but still can't get it to loop if $COUNT is greater than 140. I have scoured google and I can only find that when a while loop hits its false it will exit?
 
Last edited:
This works fine, but still can't get it to loop if $COUNT is greater than 140. I have scoured google and I can only find that when a while loops hits its false is will exit?

Yeah, thats the point. You use a while loop to do something as many times it takes until the condition is met.

If you think about it, what is it that you want to repeat and update?
Put that inside the loop. (You may need to put it before the loop as well to have a value to start with to get into the loop)

What do you only want to do one time?
Put that outside the loop.
 
This is where I am at currently:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

while [ $COUNT -lt 140 ]
 do
   echo "$FORTUNE"
   exit 0
done

This works fine, but still can't get it to loop if $COUNT is greater than 140. I have scoured google and I can only find that when a while loops hits its false is will exit?

You won't find the answer by googling. You have a structural logic problem, not a shell syntax problem.

In your loop, does the value of FORTUNE ever change? Does the value of COUNT ever change?

If the values don't change within the loop, then the conditions that cause the loop to loop won't change. A loop with unchanging loop conditions is the definition of an infinite loop. You effectively have:
Code:
while [ unchanging condition ]
do
  echo unchanging value
  exit 0 ## always executes, because && conditional removed
done
So where are the statements that cause FORTUNE and COUNT to change? Where should they be placed if you want them to occur within the loop?
 
Yeah the value changes. Fortune is a Linux command line application that gives a fortune every time it's run. I want to post this output to twitter and as you may know twitter only takes 140 characters.

So when my script runs if the fortune is less than 140 it will post. If it's greater than 140 I want it to keep running the command till a fortune less than 140 is given then post it.

For the time being I am just echoing the fortune, eventually I will be using the twidge application to post to twitter, which I already have set up and working, I'll just ammed the script once I get the loop sorted.
 
Yeah the value changes. Fortune is a Linux command line application that gives a fortune every time it's run. I want to post this output to twitter and as you may know twitter only takes 140 characters.

So when my script runs if the fortune is less than 140 it will post. If it's greater than 140 I want it to keep running the command till a fortune less than 140 is given then post it.

For the time being I am just echoing the fortune, eventually I will be using the twidge application to post to twitter, which I already have set up and working, I'll just ammed the script once I get the loop sorted.

So you need to actually run fortune inside the loop. The loop would run fortune until it gets an appropriate one. Then after the loop, you output it.
 
What is the exit condition?

Code:
#!/bin/bash 
         COUNTER=0
         while [  $COUNTER -lt 10 ]; do
             echo The counter is $COUNTER
             let COUNTER=COUNTER+1 

             ** Your Code Here **
         done

If I remember correctly, fortune just does a random line search on a text file in the system somewhere. If you run it in a loop, it will run forever, and you'll be tweeting the same crap over and over. The Twitterverse will hunt you down and beat you! LOL
 
Yeah the value changes. Fortune is a Linux command line application that gives a fortune every time it's run. I want to post this output to twitter and as you may know twitter only takes 140 characters.

I don't think you're walking through your code. You should sit down with a paper and pencil and walk through it while pretending to be the computer.

I do not mean "Imagine walking through it". I mean actually walk through it one line at a time, and actually write out what happens at each command line step. Then answer this question: Within the loop, when and where does the value of FORTUNE or COUNT change? If you can't find that place, then the problem and solution should be obvious.

In olden days this was called "bench-checking your work".
 
This is where I am at currently:

Code:
#!/bin/bash

FORTUNE=`fortune -i`
COUNT=`echo $FORTUNE | wc -m`

while [ $COUNT -lt 140 ]
 do
   echo "$FORTUNE"
   exit 0
done

This works fine, but still can't get it to loop if $COUNT is greater than 140. I have scoured google and I can only find that when a while loop hits its false it will exit?
What happens when you replace "-lt" with "-le"?
 
Thanks for all the responses guys, will be having another crack at this later on today. Will post back when I've sorted it :)

Finally got it working with an infinite loop:

Code:
FORTUNE=`fortune`

while true; do
    FORTUNE=`fortune`
    if [ "${FORTUNE:140}" == "" ]; then
        break
    fi
done

echo $FORTUNE

Thanks for all the input :)
 
Last edited by a moderator:
Finally got it working with an infinite loop:

Code:
FORTUNE=`fortune`

while true; do
    FORTUNE=`fortune`
    if [ "${FORTUNE:140}" == "" ]; then
        break
    fi
done

echo $FORTUNE

Thanks for all the input :)
Can the if-condition become the loop condition, so you won't need to break out of an infinite loop? Can you replace "while true; do" with "while [ "${FORTUNE:140}" == "" ];" or with something like it? I usually don't write bash scripts, since I'm more familiar with tcsh.

Bill
 
Can the if-condition become the loop condition, so you won't need to break out of an infinite loop? Can you replace "while true; do" with "while [ "${FORTUNE:140}" == "" ];" or with something like it? I usually don't write bash scripts, since I'm more familiar with tcsh.

Bill

I tried this originally and the script will not run, it just returns a blank.
 
Can the if-condition become the loop condition, so you won't need to break out of an infinite loop? Can you replace "while true; do" with "while [ "${FORTUNE:140}" == "" ];" or with something like it?l

Why?

Efficiency? It's a shell-script, for bog's sake.

Besides, you'd have to reverse the conditional to !=, or use the until keyword in bash.

EDIT:
Doing a little research on 'fortune' programs, it appears the most common implementations have command-line options for the length of the fortune chosen. The options -s -n 140 appear to limit fortune's output to only those epigrams shorter than 140 chars.

So as an exercise in learning shell scripting, this may have been useful. As an exercise in reading man pages before embarking on projects, maybe not so much.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.