≡ Menu

12 Bash For Loop Examples for Your Linux Shell Scripting

There are two types of bash for loops available. One using the “in” keyword with list of values, another using the C programming like syntax.

This article is part of our on-going bash tutorial series.

This explains both of the bash for loop methods, and provides 12 different examples on how to use the bash for loop in your shell scripts.

Bookmark this article for future reference, as this is the only article you would ever need to refer on how to use bash for loops with examples.

Method 1: Bash For Loop using “in” and list of values

Syntax:

for varname in list
do
 command1
 command2
 ..
done

In the above syntax:

  • for, in, do and done are keywords
  • “list” contains list of values. The list can be a variable that contains several words separated by spaces. If list is missing in the for statement, then it takes the positional parameter that were passed into the shell.
  • varname is any Bash variable name.

In this form, the for statement executes the commands enclosed in a body, once for each item in the list. For example, if the list of values contains 5 items, the for loop will be executed a total of 5 times, once for each item in the list. The current item from the list will be stored in a variable “varname” each time through the loop. This “varname” can be processed in the body of the for loop.

Method 2: Bash For Loop using C like syntax

The second form of the for loop is similar to the for loop in “C” programming language, which has three expressions (initialization, condition and updation).

for (( expr1; expr2; expr3 ))
do
 command1
 command2
 ..
done

In the above bash for command syntax,

  • Before the first iteration, expr1 is evaluated. This is usually used to initialize variables for the loop.
  • All the statements between do and done are executed repeatedly until the value of expr2 is TRUE.
  • After each iteration of the loop, expr3 is evaluated. This is usually used to increment a loop counter.

The following 12 examples shows how to bash for loops in different ways.

1. Static values for the list after “in” keyword

In the following example, the list of values (Mon, Tue, Wed, Thu and Fri) are directly given after the keyword “in” in the bash for loop.

$ cat for1.sh
i=1
for day in Mon Tue Wed Thu Fri
do
 echo "Weekday $((i++)) : $day"
done

$ ./for1.sh
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri

Caution: The list of values should not be separated by comma (Mon, Tue, Wed, Thu, Fri). The comma will be treated as part of the value. i.e Instead of “Mon”, it will use “Mon,” as value as shown in the example below.

$ cat for1-wrong1.sh
i=1
for day in Mon, Tue, Wed, Thu, Fri
do
 echo "Weekday $((i++)) : $day"
done

$ ./for1-wrong1.sh
Weekday 1 : Mon,
Weekday 2 : Tue,
Weekday 3 : Wed,
Weekday 4 : Thu,
Weekday 5 : Fri

Caution: The list of values should not be enclosed in a double quote. (“Mon Tue Wed Thu Fri”). If you enclose in double quote, it will be treated as a single value (instead of 5 different values), as shown in the example below.

$ cat for1-wrong2.sh
i=1
for day in "Mon Tue Wed Thu Fri"
do
 echo "Weekday $((i++)) : $day"
done

$ ./for1-wrong2.sh
Weekday 1 : Mon Tue Wed Thu Fri

2. Variable for the list after “in” keyword

Instead of providing the values directly in the for loop, you can store the values in a variable, and use the variable in the for loop after the “in” keyword, as shown in the following example.

$ cat for2.sh
i=1
weekdays="Mon Tue Wed Thu Fri"
for day in $weekdays
do
 echo "Weekday $((i++)) : $day"
done

$ ./for2.sh
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri

Caution: As a best practice, you should always quote the bash variables when you are referring it. There are few exceptions to this best practice rule. This is one of them. If you double quote the variable in this for loop, the list of values will be treated as single value. Lot of people fall into this trap. Be careful and do not double quote your variable in the for loop.

$ cat for2-wrong.sh
i=1
weekdays="Mon Tue Wed Thu Fri"
for day in "$weekdays"
do
 echo "Weekday $((i++)) : $day"
done

$ ./for2-wrong.sh
Weekday 1 : Mon Tue Wed Thu Fri

3. Don’t specify the list; get it from the positional parameters

If you don’t specify the keyword “in” followed by any list of values in the bash for loop, it will use the positional parameters (i.e the arguments that are passed to the shell script).

$ cat for3.sh
i=1
for day
do
 echo "Weekday $((i++)) : $day"
done

$ ./for3.sh Mon Tue Wed Thu Fri
Weekday 1 : Mon
Weekday 2 : Tue
Weekday 3 : Wed
Weekday 4 : Thu
Weekday 5 : Fri

Caution: Please be careful if you use this method. You should not include the keyword “in” in the for loop. If you leave the keyword “in” without any values, it will not use the positional parameter as shown below. It will not go inside the loop. i.e for loop will never get executed as shown in the example below.

$ cat for3-wrong.sh
i=1
for day in
do
 echo "Weekday $((i++)) : $day"
done

$ ./for3-wrong.sh Mon Tue Wed Thu Fri

Note: Refer to our earlier article to understand more about bash positional parameters.

4. Unix command output as list values after “in” keyword

You can use the output of any UNIX / Linux command as list of values to the for loop by enclosing the command in back-ticks ` ` as shown below.

$ cat for4.sh
i=1
for username in `awk -F: '{print $1}' /etc/passwd`
do
 echo "Username $((i++)) : $username"
done

$ ./for4.sh
Username 1 : ramesh
Username 2 : john
Username 3 : preeti
Username 4 : jason
..

5. Loop through files and directories in a for loop

To loop through files and directories under a specific directory, just cd to that directory, and give * in the for loop as shown below.

The following example will loop through all the files and directories under your home directory.

$ cat for5.sh
i=1
cd ~
for item in *
do
 echo "Item $((i++)) : $item"
done

$ ./for5.sh
Item 1 : positional-parameters.sh
Item 2 : backup.sh
Item 3 : emp-report.awk
Item 4 : item-list.sed
Item 5 : employee.db
Item 8 : storage
Item 9 : downloads

Usage of * in the bash for loop is similar to the file globbing that we use in the linux command line when we use ls command (and other commands).

For example, the following will display all the files and directories under your home directory. This is the concept that is used in the above for5.sh example.

cd ~
ls *

The following will display all the *.conf file that begins with either a, b, or, c or d under /etc directory.

$ ls -1 /etc/[abcd]*.conf
/etc/asound.conf
/etc/autofs_ldap_auth.conf
/etc/cas.conf
/etc/cgconfig.conf
/etc/cgrules.conf
/etc/dracut.conf

The same argument that is used in the ls command above, can be used in a bash for loop, as shown in the example below.

$ cat for5-1.sh
i=1
for file in /etc/[abcd]*.conf
do
 echo "File $((i++)) : $file"
done

$ ./for5-1.sh
File 1 : /etc/asound.conf
File 2 : /etc/autofs_ldap_auth.conf
File 3 : /etc/cas.conf
File 4 : /etc/cgconfig.conf
File 5 : /etc/cgrules.conf
File 6 : /etc/dracut.conf

6. Break out of the for loop

You can break out of a for loop using ‘break’ command as shown below.

$ cat for6.sh
i=1
for day in Mon Tue Wed Thu Fri
do
 echo "Weekday $((i++)) : $day"
 if [ $i -eq 3 ]; then
   break;
 fi
done

$ ./for6.sh
Weekday 1 : Mon
Weekday 2 : Tue

7. Continue from the top of the for loop

Under certain conditions, you can ignore the rest of the commands in the for loop, and continue the loop from the top again (for the next value in the list), using the continue command as shown below.

The following example adds “(WEEKEND)” to Sat and Sun, and “(weekday)” to rest of the days.

$ cat for7.sh
i=1
for day in Mon Tue Wed Thu Fri Sat Sun
do
 echo -n "Day $((i++)) : $day"
 if [ $i -eq 7 -o $i -eq 8 ]; then
   echo " (WEEKEND)"
   continue;
 fi
 echo " (weekday)"
done

$ ./for7.sh
Day 1 : Mon (weekday)
Day 2 : Tue (weekday)
Day 3 : Wed (weekday)
Day 4 : Thu (weekday)
Day 5 : Fri (weekday)
Day 6 : Sat (WEEKEND)
Day 7 : Sun (WEEKEND)

8. Bash for loop using C program syntax

This example uses the 2nd method of bash for loop, which is similar to the C for loop syntax. The following example generates 5 random number using the bash C-style for loop.

$ cat for8.sh
for (( i=1; i <= 5; i++ ))
do
 echo "Random number $i: $RANDOM"
done

$ ./for8.sh
Random number 1: 23320
Random number 2: 5070
Random number 3: 15202
Random number 4: 23861
Random number 5: 23435

9. Infinite Bash for loop

When you don’t provide the start, condition, and increment in the bash C-style for loop, it will become infinite loop. You need to press Ctrl-C to stop the loop.

$ cat for9.sh
i=1;
for (( ; ; ))
do
   sleep $i
   echo "Number: $((i++))"
done

Like we said above, press Ctrl-C to break out of this bash infinite for loop example.

$ ./for9.sh
Number: 1
Number: 2
Number: 3

10. Using comma in the bash C-style for loop

In the bash c-style loop, apart from increment the value that is used in the condition, you can also increment some other value as shown below.

In the initialize section, and the increment section of the bash C-style for loop, you can have multiple value by separating with comma as shown below.

The following for loop is executed a total of 5 times, using the variable i. However the variable j start with 5, and getting increment by 5 every time the loop gets executed.

$ cat for10.sh
for ((i=1, j=10; i <= 5 ; i++, j=j+5))
do
 echo "Number $i: $j"
done

$ ./for10.sh
Number 1: 10
Number 2: 15
Number 3: 20
Number 4: 25
Number 5: 30

11. Range of numbers after “in” keyword

You can loop through using range of numbers in the for loop “in” using brace expansion.

The following example loops through 10 times using the values 1 through 10.

$ cat for11.sh
for num in {1..10}
do
 echo "Number: $num"
done

$ ./for11.sh
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
...

12. Range of numbers with increments after “in” keyword

The following example loops through 5 times using the values 1 through 10, with an increment of 2. i.e It starts with 1, and keeps incrementing by 2, until it reaches 10.

$ cat for12.sh
for num in {1..10..2}
do
 echo "Number: $num"
done

$ ./for12.sh
Number: 1
Number: 3
Number: 5
Number: 7
Number: 9

PS: Don’t forget to bookmark this article for your future reference.

Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • jalal hajigholamali July 11, 2011, 2:30 am

    Hi,

    Really, very nice article
    Thanks a lot…

  • Joseph John July 11, 2011, 4:16 am

    when I run for8.sh
    I get error
    “for8.sh: 3: Syntax error: Bad for loop variable”
    I use Ubunutu 11.04
    I did cut and paste the code , did not modify anything

  • shark巨菜 July 11, 2011, 5:33 am

    such many way
    ( ⊙ o ⊙ )!

  • Marija July 11, 2011, 7:10 am

    @Joseph John . . .for8.sh works for me….using bash shell

  • Júlio Hoffimann Mendes July 11, 2011, 9:19 am

    Thanks Ramesh!

    I knew all bash loops you showed, is great to see them joined in one page. This helps so much whom is learning this useful language. 🙂

    Regards,
    Júlio.

  • Joseph John July 11, 2011, 10:09 pm

    @Marija , I tried using bash “for8.sh” and it is working
    thanks

  • Bilal Bhat July 11, 2011, 10:52 pm

    Good one…will use most of examples in practical….

  • Kamal Kishore July 12, 2011, 6:51 am

    cat for12.sh
    for num in {1..10..2}
    do
    echo “Number: $num”
    done

    Above example is not working….
    Output is comming as follows…..
    for num in {1..10..2}

  • robin July 12, 2011, 9:50 am

    quote” Kamal Kishore”

    cat for12.sh
    for num in {1..10..2}
    do
    echo “Number: $num”
    done

    Above example is not working….
    Output is comming as follows…..
    for num in {1..10..2}

  • Pier July 12, 2011, 2:05 pm

    thanks Ramesh,

    I knew the “classic” bash syntax (but it is always good to pop up some old knowledge) but i totally discovered the “C” style syntax!

    I won’t bookmark this page as i already bookmarked your site!

  • jalal hajigholamali July 12, 2011, 8:07 pm

    for num in {1..10..2}
    do
    echo “Number: $num”
    done

    under bash is working
    output is:
    “Number: 1”
    “Number: 3”
    “Number: 5”
    “Number: 7”
    “Number: 9”

  • Andrius Bentkus July 14, 2011, 6:48 am

    I always disliked bash, but at least it has some good bits.
    Though I doubt it that it will be the next javascript (a language which was very much disliked by everyone in the early days but gains some popularity now).

  • Ken Butcher July 16, 2011, 6:58 am

    A simpler variation of the infinite for loop:
    $ cat for9-a.sh
    i=1;
    for :
    do
    sleep $i
    echo “Number: $((i++))”
    done

  • EmcySquare July 18, 2011, 3:11 am

    About the ” Syntax error: Bad for loop variable”
    Be sure to use BASH and not SH as interpreter

  • Ken Butcher July 18, 2011, 11:08 am

    Correction to my earlier post. The alternate infinite for loop using the : (nop) operator must be while, not for. i.e.
    while :
    do
    sleep $i
    echo “Number: $((i++))”
    done

  • Ken Butcher July 18, 2011, 11:16 am

    For those using Ubuntu, be aware that Dash is the symbolic link for sh instead of the traditional Bash. For other distros, you can test this using
    ls -l `which sh`
    and if it is dash, you can change it back to bash with
    cd /bin
    sudo rm sh
    sudo ln -s bash sh

  • anon March 5, 2012, 4:37 am

    You’re the best 😀

  • Deepak April 24, 2012, 11:22 am

    Gr8 Article f 🙂

  • Glenn May 7, 2012, 3:23 pm

    One thing you left off was the one line format:

    $ for foo in a b c ; do echo $foo; done

    Note the added semi-colons indicating the end of each statement.

  • Varun May 29, 2012, 11:51 pm

    Hi Friends,

    I tried for loop as below.

    for i in {“$start”..”$end”}

    where start and end are user input variable. Its throwing error as:
    syntax error: operand expected (error token is “{2..5}”)

    Please help me where I have to give this operand ‘(‘.

    Looking for your reply.
    Thanks
    Varun S

  • Ken B May 30, 2012, 2:58 pm

    eval for i in {$start..$end}\;do echo \$i\;done

  • Rajesh Kumar V July 18, 2012, 7:46 am

    Hi ramesh/team,

    how to use multiple variable in single “for” loop .if not possible pls give alternate solution .

    i am trying
    for file in $(cat 2) && for ID in $(cat 3)
    do
    echo “Modifying file : $file and $ID ”
    echo “” >> $file.tmp
    cat $file >> $file.tmp
    mv $file.tmp $file
    done

    But Not working .
    please help me on this.

    thanks in advance
    Rajesh /JDHP

  • sharan August 15, 2012, 2:09 pm

    @Ken Butcher Thanks a lot for your comment … i had a project deadline .. and was struck doing the benchmarks with the error bad loop variable … after doing the change you have given , I got it solved.. again thanks a lot…

    @Ramesh clean and simple… great article

  • Venadan September 4, 2012, 6:50 am

    Awsome examples…and use almost every day..great job !!!

  • E September 25, 2012, 8:39 am

    What about for adding numbers to the end of a file if it is already detected while being copied?
    ex. copy file 1
    ok
    copy file 1 again
    file one renamed as file 1(2)
    ect..

  • Ken B September 25, 2012, 6:57 pm

    google bash backup version control

  • shweta October 14, 2012, 12:18 am

    for i in {$start..$end}
    do
    echo ” i m $i”
    done
    where start and end are user input variable,
    Above example is not working……
    output is – i m 2..7
    as 2 and 7 are the user inputs…………
    Pls help me ……….

  • Maine_guy October 16, 2012, 2:11 pm

    shweta,
    Bash doesn’t work that way. you can use {2..7} but not {$a..$b}
    A work around is
    for (( i=$start; i<=$end; i++ ))
    do
    echo ” i m $i”
    done

  • shweta October 16, 2012, 11:28 pm

    @ MAine_guy thanks………. it solved my confusions………

  • Maine_Guy November 1, 2012, 10:57 am

    Another way:

    for i in $(seq $start $end); do
    echo “i m $i”
    done

  • udayakanta November 12, 2012, 4:50 am

    all info abt for loop…….i got it……..thanks….

  • Nic December 25, 2012, 10:48 am

    I’ve never been able to get bracket expansion to work in a loop…

    somaddict@terrordome ~/sandbox
    $ for i in [abcd] ; do echo $i;done
    [abcd]

    somaddict@terrordome ~/sandbox
    $ for i in {a..d}; do echo $i;done
    a
    b
    c
    d

  • shilpa n chinnannavar March 6, 2013, 11:20 am

    i want shell script programs from simple to complex..
    if u guys help me it will be useful for me..
    very thanks in advance

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

  • Maine_Guy April 15, 2013, 3:19 pm

    Mathisin, Change #!/bin/sh to #!/bin/bash and your script will run without error.
    /bin/sh used to be a symbolic link to /bin/bash but now it is a symbolic link to /bin/dash

  • Nagendra November 19, 2013, 9:28 am

    Hi I need to use like this
    for i in $list j in $list1
    do
    done
    may i know is there any chance like this

  • Narayan January 29, 2014, 7:18 am

    thank you

  • bill February 3, 2014, 10:45 am

    in solaris 10
    for i in {1..254}; do ping 172.20.140.$i 1 |grep alive;done

  • Debashis March 25, 2014, 12:14 am

    Many thanks for the help. From this page I got all the information I was searching for my script.

  • Amadou Coulibaly June 10, 2014, 7:18 am

    I really found these examples very helpful for those who are beginners in Shell Scripting using both bash and sh. Personnaly, it has helped me to better understand For Loops in Shell Scripts.

    Thank you very must for posting those kinds of knowlege online.

  • Aashish June 16, 2014, 4:40 pm

    Below code executed successfull but output will be not generated.. even its not print echo $var also. Where is it wrong. Similar as your example Number 4. Please help..

    for var in `ps –help|grep Try|cut -d’>psoption
    done

  • sahil June 26, 2014, 6:19 am

    Can anyone tell me ..i am using for loop in ksh …but i want to use without seq
    for (( i=$start; i<=$end; i++ ))
    do
    echo ” i m $i”
    done

    bt not working

  • Maine_Guy June 26, 2014, 1:28 pm

    sahil: see my comment above about bash vs. sh. Your code works in bash but not in sh

  • ash July 7, 2014, 6:36 am

    nice articles, do you have any other posting for other loops like while and arithmetic operations, file handling etc.

  • Ravi Tyagi October 15, 2014, 4:40 am

    @@@@ Sahil

    for (( i=1; i<=10 ;i++ )) ; do echo "i m $i" ;done

  • Mircea Alexandru Ticovschi June 2, 2015, 8:40 am

    Backing up files
    for i in ls * ; do echo “Backing up file: $i”; cp $i $i.bak; done

  • palanisamy July 13, 2015, 6:19 am

    i=1

    for file in `awk -F: ‘{print $1}’ /praksh/[abcd]*.xml`
    do
    echo “File $((i++)) : $file”
    done

    Could you please i have issue on the above script ?

    Error: gawk: cmd. line:2: fatal: cannot open file `/praksh/[abcd]*.xml’ for reading (No such file or directory)

  • Surinder Singh September 6, 2015, 5:46 am

    Awesome tutorial..
    only this did not worked.
    i=1
    for day
    do
    echo “Weekday $((i++)) : $day”
    done

  • Trinadharao MM December 13, 2015, 11:07 pm

    I have this script saved as /usr/local/bin/timenow.sh and it contains the following:

    #!/bin/bash
    d1=”$(date +”%d-%b-%Y”)”;
    t1=”$(date +”%l:%M %p”)”;
    da1=”$(date +”%A”)”;
    eval “export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME xfce4-session)/environ)”;
    /usr/bin/notify-send “Date & Time reminder:” “$d1 \n””$t1 \n””$da1” -i “/usr/share/pixmaps/gnome-computer.png” -t 9000;
    exit 0;

    I have add the cron job for this script to run every day at 5pm to alert users of the logout time and it works fine. But this is working only for for a single user because i manually set it as a cron job for this parituclar user. Most users are connected remotely to this ubuntu server (LTSP environment) and so I need to configure the crontab through root user in such a way that it must alert every logged in user on the server. Any help please? If there’s a possible way to run this script as a root user and call the DBUS_SESSION_BUS_ADDRESS of each logged in user and set them in an array and execute it in a loop until it shows the notification to all the logged in user sessions or any other method?

  • Suruchi January 14, 2016, 6:15 am

    How to print a series 1 -2 3 -4 5 -6 7

  • Sowpna February 11, 2016, 10:40 pm

    Explanation is very good and flaw less. I always like your articles. Please keep posting.

  • Farhad Alam March 5, 2016, 10:54 pm

    good article

  • Anonymous May 2, 2016, 11:36 am

    Neither of these methods working. every time i try to work run these scripts i get “./week.sh[5]: i++: more tokens expected” this error

  • Bruce April 4, 2017, 12:08 pm

    The braces will expand leading zeros (with a current bash).
    So:

    $ for i in {000..1}; do echo $i; done

    Will expand to:

    000
    001

    But variables will expand to string thusly:

    some_input=1=3000
    for i in {000..$some_input}; do echo $i; done

    results in a string, not an array expansion. Thus the output is:
    {000..3000}

    As mentioned: Using eval will work, but is messy for multi-line code.