-   Programming (
-   -   'for' loop in bash script (

vjramana 05-13-2012 07:39 AM

'for' loop in bash script
Dear experts,

I am writing a bash script. At some point of the program I need to have 'for' loop. For simplicity I tried with some other simple code. The format of the loop is given below.



for j in {$k..$m};do

echo "$w, $z"


But my code is fail to run.

Basically I want the k and m to variable.

Can anyone address some point here?
Appreciate any help in advance.


colucix 05-13-2012 08:28 AM

This is because brace expansion is performed before variable expansion, so that the string inside the braces is interpreted literally as

Look at this and notice the different shell expansions are performed in the order they are exposed.

In your case better to use the seq command:

for j in $(seq $k $m)

or the alternate C-like form of the for loop:

for (( j=$k; j<=$m; j++ ))

Hope this helps.

pixellany 05-13-2012 09:02 AM

this is the line with the issue:

for j in {$k..$m};do
......but, I cannot find how to do it correctly...:confused:

This works:

for j in {1..5}
is it not possible to have variable expansion in this construct???

pixellany 05-13-2012 09:04 AM

sigh....while I founder, an expert answers.....;)

David the H. 05-13-2012 09:12 AM

Two of the best pages to look at first when you come across scripting problems are the Bash Pitfalls and FAQ pages.

In this case the problem is described in pitfall #33. Doing your counting with a c-style loop is usually more efficient and less prone to error anyway.

Read the excellent Bash Guide from the same source for a good tutorial on scripting basics.

Edit: BTW, when operating in arithmetic contexts, variables don't usually need to be prefixed with "$". Since string literals are invalid, they are automatically assumed to be variables and expanded.


w=$(( j+2 ))

lithos 05-13-2012 09:15 AM

May I add, that similar I had done with WHILE loop

# number of drives
DRIVESNO=$(grep 'physicaldrive' $CHECKfile | grep -c ':id')


while [ $i -lt "$DRIVESNO" ]


echo "Drive $i: $(grep "physicaldrive 2:$i" $CHECKfile )" >>$RAIDSTATUSFILE

It may be that you can do it like this ?

David the H. 05-13-2012 11:04 AM


Seems a bit overly-complex and wasteful to me; it does exactly the same thing as c-style for loop, only less cleanly and concisely.

Also, "$[..]" is non-standard and deprecated. Use "((..))" instead, or "$((..))" if you need posix compatibility. You can also use the let keyword.


(( i++ ))        #bash or ksh form; uses ++ for simple value incrementing.
: $(( i++ ))        #posix compatible, prefixing it with the ":" (true) command keeps it from producing output.
i=$(( i + 1 ))        #using the original long syntax
let i++
let i=i+1

And if I may add a few more scripting points:

Clean, consistent formatting makes code readable and more easily debuggable. Indent all your sub-commands, and separate logical sections with whitespace. Add comments anywhere the code isn't completely obvious (and remember, what seems obvious to you now will not be so a year or so down the line).

Many people also feel that it's more readable to place the "do/then" keywords on the same line as the "for/while/until/if" keywords, as it more clearly separates the outside block from the inside block.


for var in fee fai foo fum ; do

        if [[ "$var" == "foo" ]]; then
                echo "Found 'foo'."


When using bash or ksh, it's recommended to use ((..)) for numerical tests, and [[..]] for string/file tests and other complex expressions. Avoid using the old [..] test unless you specifically need POSIX-style portability.

QUOTE ALL OF YOUR VARIABLE SUBSTITUTIONS! You should never leave the quotes off a parameter expansion unless you explicitly want the resulting string to be word-split by the shell (globbing patterns are also expanded). This is a vitally important concept in scripting, so train yourself to do it correctly now.

Since environment variables are generally all upper-case, it's good practice to keep your own user variables in lower-case or mixed-case, to help differentiate them.

It would probably also be more efficient to save the first grep output into an array first, so that you only have to run it once. Then you could check that as needed for the values you want. I don't know what the contents of the $CHECKfile looks like, though, or else I could post an updated version.

All times are GMT -5. The time now is 03:03 AM.