views:

124

answers:

3

I've never done shell script before and now I'm running into a simple problem... I have a for loop which executes every time the run.sh script. To see how far the script has already run I want to print e.g. every 5000 the actual index.

$counter = 0
for ((  i = 0 ;  i <= 5000;  i++  ))do
    if ($i =  $counter); then
            echo "$counter"
            counter=$(counter+1000)
    fi
./run.sh
done

running this piece of code gives me the following error

./for_loop.sh: line 1: =: command not found
./for_loop.sh: line 3: 0: command not found

I have also tried to init the variable counter with

declare -i counter = 0

which gives me the following error

./for_loop.sh: line 1: declare: `=': not a valid identifier
+1  A: 

In line 3 I believe you have mistaken assignment = for equality ==

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic

Jed Schneider
+2  A: 

You don't really need two counters. A single counter will suffice:

for (( counter = 0; counter <= 5000; counter++ ))
do
    if (( counter % 1000 == 0 ))
    then
            echo "$(( counter / 1000 ))"
    fi
    ./run.sh
done

This executes run.sh 5000 times and prints the counter value every 1000 iterations. Note that % is the modulus operator which computes remainder after division and / is the integer division operator.

Derek Mahar
thanks for your nice solution!the command echo "%(( counter / 1000 ))" prints actually %(( counter / 1000 )) and not the result of counter/1000. Do you know where the problem is?
mkn
Oops! `%(( counter / 1000 ))` should read `$(( counter / 1000 ))`. Replace the `%` with a `$`. I corrected my answer.
Derek Mahar
oh of course... could have found it out by myself :) thx again
mkn
+3  A: 

Line 1 should be: (No $, no extra spaces around '=')

counter=0

Line 3 should be: (Square brackets, '-eq' because '=' is for string equality)

if [ $i -eq $counter ]

Line 5 should be: (Double parentheses)

counter=$((counter+1000))
schot
In the for-loop, there should also be a semicolon between `))` and `do`, or `do` should be on the next line.
Derek Mahar
You are right, but for some reason the `for (( .. ))do` runs fine on my machine (bash 3.2.17).
schot
What about `for (( .. )) do`, that is, with a space between the last closing parenthesis and `do`? Perhaps Bash accepts the closing parenthesis as a delimiter replacement for the `;`.
Derek Mahar
That also works. I guess the `for (()) do` is easy enough to parse. But I agree it is bad style to omit the semicolon or newline here.
schot
Line 3 could also be `if ((i == counter)); then` (just double the parentheses and the equal sign and you can omit or retain the dollar signs). Line 5 could be `(( counter += 1000 ))`. Also, in line 1 there shouldn't be a space *after* the equal sign either.
Dennis Williamson
@Dennis You are right on all counts: like in perl, there's more than one way to do it. I usually write POSIX sh instead of bash. And I removed the space after the '='.
schot
@Dennis: This is form of if-statement condition that I used in my answer, http://stackoverflow.com/questions/3422827/for-loop-if-condition-in-shell-script/3422983#3422983.
Derek Mahar
@Derek: Yep, that's one of the reasons I upvoted you earlier.
Dennis Williamson