Shell Script While Loop Examples

by on July 16, 2009 · 22 comments· LAST UPDATED July 16, 2009

in , ,

Can you provide me a while loop control flow statement shell script syntax and example that allows code to be executed repeatedly based on a given boolean condition?

Each while loop consists of a set of commands and a condition. The general syntax as follows for bash while loop:

while [ condition ]
do
	command1
	command2
	commandN
done
  1. The condition is evaluated, and if the condition is true, the command1,2…N is executed.
  2. This repeats until the condition becomes false.
  3. The condition can be integer ($i < 5), file test ( -e /tmp/lock ) or string ( $ans != "" )

ksh while loop syntax:

while [[ condition ]] ; do
	command1
	command1
	commandN
done
 

csh while loop syntax:

     while ( condition )
         commands
     end
 

BASH while Loop Example

#!/bin/bash
c=1
while [ $c -le 5 ]
do
	echo "Welcone $c times"
	(( c++ ))
done

KSH while loop Example

#!/bin/ksh
c=1
while [[ $c -le 5 ]]; do
	echo "Welcome $c times"
	(( c++ ))
done

CSH while loop Example

#!/bin/csh
c=1
while ( $c <= 5 )
	echo "Welcome $c times"
	@ c = $c + 1
end

Another example:

#!/bin/csh
set yname="foo"
while ( $yname != "" )
	echo -n "Enter your name : "
	set yname = $<
	if ( $yname != "" ) then
		echo "Hi, $yname"
	endif
end
TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 22 comments… read them below or add one }

1 Ronald Fischer July 16, 2009 at 11:15 am

IMHO, your examples are incomplete in that they leave out some cases which are perhpas more important than what you provide.

What you present as a bash example is, while still working in bash, really old-style Bourne Shell syntax (the ‘[‘ being syntactic sugar for the ‘test’ command). In bash too, I would use most of the time the more flexible

while [[ ... ]]

syntax. In addition, you are missing two useful cases:

while COMMAND
do

done

which evaluates a COMMAND until it returns an exit code not-equal zero; this works on the non-csh shells (bash, ksh, zsh,..). An then in bash (version 3.0 and higher) and zsh (maybe also in ksh – this I don’t know) you have the important special case of COMMAND being an arithmetic expression:

while ((CONDITION))
do

done

In bash 2.x you would have to write

while $((….))
do

done

In the last version, you have to expand variables inside the expression by prepending a $ sign, while in the ((…)) version you can use just the variable name without a $.

Reply

2 Danny July 23, 2009 at 7:10 pm

You don’t use $variables inside of (()) or $(()), due to the way variable expansion works. Using the $variables inside can change the order of operations (examples left as an exercise for the reader), whereas leaving the $ off makes things more predictable (IMHO). Never mind that $(()) gets expanded to the value of the arithmatic operation inside. Boolean operations expand to either 0 or 1. So,

while $(( 1 < 2 ))

is equivalent to typing

while 1

which will fail, because the shell will try to run a command named "1". Try it – it doesn't work in any commonly used Bourne-style shell. :)

Also, for the sake of completeness: in ksh you can use while (( )) as well, but that may just be ksh93 and later. IMHO, the only benefit of (()) v/s [[]] is that you can use < instead of -lt, which is a pretty small gain for the tradeoff of using two different bracket styles. More consistent code is more readable and less likely to get messed up.

I do agree that [[]] is better than [], though (even though [ is a shell builtin in all modern shells, so isn't the performance killer it used to be on really old POSIX sh implementations)

Reply

3 Shantanu Oak July 24, 2009 at 5:32 am

It is also possible to feed the while loop after “done” like this…

RECORDFILELIST=/root/branch_records.lst

while read RECORDFILENAME
do


done < $RECORDFILELIST

Reply

4 Ronald Fischer July 27, 2009 at 7:04 am

Danny, you are right. I should have checked the while $((…)) before posting. If someone really wants to use $((…)) expansion in a ‘while’ for whatever reason, it needs to be done with a test command, i.e.

while [[ $((...)) ]]

but of course while ((…)) makes more sense.

Thanks also for pointing out the possibility of omitting the $ in front of variables inside a $((…)). I thought this was only possible inside ((…)), but I verified that at least since bash 2.x, this works as you described.

Reply

5 leo main November 24, 2009 at 7:34 am

would you give out a practical example next time in c++.
thank you.

Reply

6 Ronald Fischer November 26, 2009 at 8:06 am

Maybe also in LISP?

Seriously, as the title of the posting might suggest, this is for shell scripting. But of course as soon as you can find a C++ based shell scripting language, we could think this over :-D

Reply

7 Hemendra Singh August 25, 2010 at 9:29 am

Check out this code for while loop [ Tested on Open Solaris , Shell - Bash ]

# To print numbers from 1 to 10 — This is a comment

i=1
while((i <=10)
do
echo $i
i=`expr $i + 1`
done

Reply

8 D Nagarjuna Rao September 13, 2011 at 4:55 pm

# To print numbers from 1 to 10 — This is a comment
i=1
while((i <=10))
do
echo $i
i=`expr $i + 1`
done
try this,
it can works

Reply

9 Hassan August 8, 2011 at 3:30 am

* In exercise , we have used ‘locate’ as a simple and fast way to locate files
(directories) by typing something like :
locate Kuala
* This works .
* For this assignment, you will write a more user-friendly utility, one that ‘talks’ to the
user, asks the user what (s)he wants to do, etc.
*You also don’t know, when the database has been updated last (Hint, hint!) :
locate Kuala SysAdmin_Lab12
* shows both the occurrences of ‘Kuala’ and ‘SysAdmin_Lab12′. But not necessarily in this sequence. And
locate Kuala bin
* surely shows much too many, since there are all the files in the system directories (bin/ and /sbin) that will be shown and the few with ‘Kuala’ become invisible in the large amount. I am sure, you get the idea … .
What about (I am dreaming, I know! – but to give an example of a sample program):

$ myloc
This utility shows you all files and directories that have a specific
substring in the name.
Press ‘?’ for help, ‘q’ for quit or enter your search terms:
Kuala bin
I have searched for two terms for you,
Kuala, which has three hits:
/usr/share/zoneinfo/Asia/Kuala_Lumpur
/usr/share/zoneinfo/posix/Asia/Kuala_Lumpur
/usr/share/zoneinfo/right/Asia/Kuala_Lumpur
bin, which has 2312 hits. Are you sure you want to see all of those? [Y/n]
n
Press ‘?’ for help, ‘q’ for quit or enter your search terms:
Sorry-lah, you didn’t enter any search term.
Press ‘?’ for help, ‘q’ for quit or enter your search terms:
q
Thanks for being here, come again.
$

$ myloc Kuala
I have searched for one term for you,
Kuala, which has three hits:
/usr/share/zoneinfo/Asia/Kuala_Lumpur
/usr/share/zoneinfo/posix/Asia/Kuala_Lumpur
/usr/share/zoneinfo/right/Asia/Kuala_Lumpur
Press ‘?’ for help, ‘q’ for quit or enter your search terms:
q
Thanks for being here, come again.
$

* Your task is, to work on this problem either individually, or in groups of two.
The task must be implemented, and run as a single program written in shell script,
with the name of the program being ‘myloc’, and stored in your home directory.
Once the program is ready, you run a script (replace sn012345 with your id; and
sn098765 if you worked in a group of two, with sn098765 the other’s student-id):

1. The exact text used in the examples as above is not what I want! If your program
produces the same wording, I will even reduce your marks due to lack of fantasy,
imagination and creativity.
3. Before sending the output of the script file, check that it is not too big. You don’t
want me to have to scroll through thousands of lines, do you? In order for me to be (and willing) to read it, it must be below 100kB.

**** this is an assignment I got in one of the lecturer … some one answer it and send it to me if you can !!

Reply

10 Ronald August 8, 2011 at 8:46 am

Hi Hassan,

I don’t see how your question is related to the “while loop example”…

Reply

11 Andy January 23, 2012 at 10:34 am

Hi there… I’m trying to get this function to work on ksh:
wait_for() {
res=0
while [[ ! $res -gt 0 ]]
do
res=$(tail -5 “$START_LOG” | fgrep -c “$1″)
sleep 5
done
}

can anyone help please?

Thanks,

Reply

12 Jason February 14, 2012 at 5:00 pm

Not sure exactly why inside the function that it gets confused by the quotes, but simply leaving off the double-quotes should get your desired effect:
wait_for() {
res=0
while [[ ! $res -gt 0 ]]
do
res=$(tail -5 $START_LOG | fgrep -c $1)
sleep 5
done
}

Reply

13 Gerald March 31, 2012 at 5:36 pm

!!!!!!!!!!!!!PLEASE HELP!!!!!!!!!!!!!
HOW WOULD I MAKE THE FOLLOWING SHAPE USING A WHILE LOOP IN A SCRIPT?
*
***
*****
******
********
*
IN OTHER WORDS A CHRISTMAS TREE SHAPE. YOUR HELP WILL BE MUCH APPRECIATED!!!

Reply

14 Anish August 8, 2012 at 5:15 am

Thanks…..
please send me solution of other problems

Reply

15 maisam August 24, 2012 at 8:34 am

i=1
while((i <=10)
do
echo $i
i=`expr $i + 1`
done

Reply

16 sam October 9, 2012 at 12:22 pm

i am looking for a shell script program to find the user log in and log out timing for each 5 second…can any one please tell me the script coding..

or please correct this and post here………
this is for unique user id

$ cat lag.sh
#!/bin/ksh
echo "The current users are:"
who | awk '{print $1}' | sort > temp1
cp temp1 temp2
more temp1
while true
do
who | awk '{print $1}' | sort > temp2
cmp -s temp1 temp2
case "$?" in
1)
user="adcwcgq"
file=`grep $user temp1 temp2 | cut -c 1-5`
echo $file
file1=`echo $file | cut -c 1-5`
echo $file1
if [ $file1 = "temp1" ]
then echo "User "$user" has logged out." | mail -s "Logged out" abc@xyz.com
cat /home/absprod1/test_audit | mail -s "Audit report" abc@xyz.com
fi
esac

but i need it for all user who logged …..

i have tried this coding…….but its also showing error..please correct this two coding and tell me the solution or write by ur own coding and paster here … Many thanks in
advance…..

$ cat log*
#! /bin/sh
echo "The current users are:"
who | awk '{print $1}' | sort > temp1
cp temp1 temp2
more temp1
while true
do
    who | awk '{print $1}' | sort > temp2
    cmp -s temp1 temp2
    case "$?" in
    0)
        echo "No user has logged in/out in the last 5 seconds."
        ;;
    1)
        user=`comm -23 temp1 temp2`
        file=`grep $user temp1 temp2 | cut -c 1-5`
        if [ $file = "temp1" ]
            echo "User "$user" has logged out."
        if [ $file = "temp2" ]
            echo "User "$user" has logged in."
        ;;
    esac
    rm temp1
    mv temp2 temp1
    sleep 5
done

Reply

17 tom January 8, 2013 at 5:53 am

someone help.
I cant get this working.
When i run this script, it should give me some messages(part of script)
but no errors, just does nothing.

while true
do
SLEEP=`cat /sys/power/wait_for_fb_sleep`
AWAKE=`cat /sys/power/wait_for_fb_wake`
#screenoff.
if [ $SLEEP = sleeping ]
then
sh /system/mpengine/mpe10/mpe10_screenoff
fi
#exception.
if [ $COKE -le $TOTALMEM -a $COKE -gt $REALTOTALMEM -a $REALFREEMEM -le $MFK -a $AWAKE = awake ]
then
sh /system/mpengine/mpe10/mpe10_exception
#flusher.
elif [ $COKE -le $REALTOTALMEM -a $COKE -gt $CUSTOMTOTAL -o $REALFREEMEM -lt $MFKLIMIT -a $AWAKE = awake ]
then
sh /system/mpengine/mpe10/mpe10_flusher
#mix-up.
elif [ $COKE -le $CUSTOMTOTAL -a $COKE -gt $ENDOFTHEWORLD3 -a $REALFREEMEM -ge $MFKLIMIT -a $AWAKE = awake ]
then
sh /system/mpengine/mpe10/mpe10_mix-up
#mix-up2.
elif [ $COKE -le $ENDOFTHEWORLD3 -a $COKE -gt $ENDOFTHEWORLD32 -a $REALFREEMEM -ge $MFKLIMIT -a $AWAKE = awake ]
then
sh /system/mpengine/mpe10/mpe10_mix-up2
#powersaver.
elif [ $COKE -le $ENDOFTHEWORLD32 -a $COKE -ge $MEMINUSE -o $REALFREEMEM -ge $MFKLIMIT -a $AWAKE = awake ]
then
sh /system/mpengine/mpe10/mpe10_powersaver
#exception2.
else
sh /system/mpengine/mpe10/mpe10_exception2
fi
done

Reply

18 mathison April 15, 2013 at 6:58 pm

Im trying to run each comand then the next one in a loop. im getting an error?

/etc/init.d/FMtx.sh: 3: /etc/init.d/FMtx.sh: Syntax error: Bad for loop variable

???
—————————
#!/bin/sh

for ((i=0;i<6;i++))
do
sudo /home/pi/pifm botID.wav 90.3
sudo /home/pi/pifm nightlife_01.wav 90.3
sudo /home/pi/pifm –
sudo /home/pi/pifm wwrob2.wav 90.3
sudo /home/pi/pifm –
sudo /home/pi/pifm mae.wav 90.3

echo $i
done
—————————–

Reply

19 gopi September 8, 2013 at 11:55 am

Please use #!/bin/bash as the inerpreter in the above example it will work

Reply

20 hema December 9, 2013 at 10:56 am

write a script to input the filename and display the content of file in such a manner that each line has only 10 characters.If line in a file exceeds 10 characters then remaining characters should be printed in the next line..

Reply

21 hema December 9, 2013 at 10:58 am

A text file email.txt contains fields email address from,email address to display report which give detail of email sent by particular person…

Plzzzzzzzzzz help me….

Reply

22 vamshi September 27, 2014 at 6:43 am

please help me to do below problem using shell scripting loops
*
**
***
****

Reply

Leave a Comment

Tagged as: , , , , , , , , , ,

Previous Faq:

Next Faq: