bash script calling itself with different arguments

I just can not get it right.

Script takes two arguments, target and command. Valid targets are specified within an array. If target is ‘all’, script should iterate through all targets.

#!/bin/bash
# recur.sh

targets=('aaa' 'bbb' 'ccc' 'ddd')

if [ "$1" == "all" ] ; then
    for i in $targets ; do
        echo $2" --> "$i
        ./$0 $i $2
    done
    exit 0
fi

echo "Target "$1" just received command '"$2"'"

exit 0

I expect the following output:

$ recur all boggle
boggle --> aaa
Target aaa just received command 'boggle'
boggle --> bbb
Target bbb just received command 'boggle'
boggle --> ccc
Target ccc just received command 'boggle'
boggle --> ddd
Target ddd just received command 'boggle'

But the script exits at the first iteration:

$ recur all boggle
boggle --> aaa
Target aaa just received command 'boggle'
Asked By: Lorinc Nyitrai

||

The problem isn’t in the recursion, it’s in the looping over the items. If you try this as above, you don’t get what you expect:

$ targets=(aaa bbb ccc ddd)
$ for i in $targets; do echo $i; done
aaa

To loop over the array, you need to generate a list of the items in the array, as per,eg, this link:

So you have

#!/bin/bash
# recur.sh

targets=('aaa' 'bbb' 'ccc' 'ddd')

if [ "$1" == "all" ] ; then
    for i in ${targets[@]}; do
        echo $2" --> "$i
        ./$0 $i $2
    done
    exit 0
fi

echo "Target "$1" just received command '"$2"'"

exit 0
Answered By: Jonathan Dursi

The problem, is that you have not looped over all elements in array, just one element, because you used $targets instead of ${targets[@]}.

Try this fix:

targets=('aaa' 'bbb' 'ccc' 'ddd')

if [ "$1" == "all" ] ; then
    for i in ${targets[@]} ; do
        echo $2" --> "$i
        echo "Target "$i" just received command '"$2"'"
    done
fi

exit 0

You don’t need recursion here.

Answered By: cuonglm

Others already pointed out, the problem with the syntax used when accessing a list. But that’s not the only problem with your script. You are also using variables without quoting. When using $variablename without quotes, you are going to get unexpected results, if that variable contains any characters, which could be interpreted by the shell.

Here is how I would change your script to avoid such problems:

#!/bin/bash
# recur.sh

targets=('aaa' 'bbb' 'ccc' 'ddd')

if [ "$1" == "all" ] ; then
    for i in "${targets[@]}"; do
        echo "$2 --> $i"
        "$0" "$i" "$2"
    done
    exit 0
fi

echo "Target $1 just received command '$2'"

exit 0

You should make it a habit to always put usage of variable inside double-quotes, unless you have a very good reason not to.

Answered By: kasperd
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.