≡ Menu

Shell Script While Loop Examples

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
Tweet itFacebook itGoogle+ itPDF itFound an error/typo on this page?

{ 24 comments… add one }

  • Ronald Fischer July 16, 2009, 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 $.

  • Danny July 23, 2009, 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)

  • Shantanu Oak July 24, 2009, 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

  • Ronald Fischer July 27, 2009, 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.

  • leo main November 24, 2009, 7:34 am

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

  • Ronald Fischer November 26, 2009, 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

  • Hemendra Singh August 25, 2010, 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

    • D Nagarjuna Rao September 13, 2011, 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

  • Hassan August 8, 2011, 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 !!

  • Ronald August 8, 2011, 8:46 am

    Hi Hassan,

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

  • Andy January 23, 2012, 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,

  • Jason February 14, 2012, 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
    }

  • Gerald March 31, 2012, 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!!!

  • Anish August 8, 2012, 5:15 am

    Thanks…..
    please send me solution of other problems

  • maisam August 24, 2012, 8:34 am

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

  • sam October 9, 2012, 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
    
  • tom January 8, 2013, 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

  • mathison April 15, 2013, 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
    —————————–

    • gopi September 8, 2013, 11:55 am

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

  • hema December 9, 2013, 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..

    • hema December 9, 2013, 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….

  • vamshi September 27, 2014, 6:43 am

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

  • TANVEER MUSTAFA May 13, 2015, 12:48 pm

    the while loops defined above r not running….error : unexpected error

  • Paulo M.S July 4, 2015, 12:43 am

    Muito bom, me ajudou muito mesmo!!! valeu

Leave a Comment