Loop through 2 arrays with bash

anverhousseini
Contributor II

Hi Guys

We use a multi context environment. For deploying scripts, packages etc. on all contexts I am using the API. I'm currently working on a shell script which contains 2 arrays (contexts and the XML's). How do I loop through those two arrays without creating a huge script? I created this so far:

#!/bin/bash

#   variables
    jss=https://jss.example.com:8443
    user=example
    password=example
    filepath=~/Scripts/
    jssresource=JSSResource/scripts/id/0

#   all xml in one array
    xml=(
        'script1.xml'
        'script2.xml'
        'script3.xml'
        'script4.xml'
        'script5.xml'
    )

#   all context in one array
    context=(
        'test1'
        'test2'
        'test3'
        'test4'
        'test5'
    )

#   loop through context and XML
    /bin/echo "`date`: Loop through context and XML"

    for ((i = 0; i < "${#context[@]}"; i++))

        do

            /bin/echo "`date`: POST ${filepath}/${xml[$i]} to ${jss}/${context[$i]}"
            /usr/bin/curl -k -v -u "$user":"$password" "$jss/${context[$i]}/$jssresource" -T "$filepath"/"${xml[$i]}" -X POST

        done

#   exit
    exit 0

But from here my bash experience stops. Any hints how do I finish this sript?

1 ACCEPTED SOLUTION

mm2270
Legendary Contributor III

@anverhousseini If the issue is what I mentioned above, the trick is you need to include an additional for loop within the one you have that handles all the items in the scripts array. But you have to specify a different character as a placeholder for the array indices.

I copied/pasted your script into TextWrangler and added this as shown below. Give this a try. Note that I'm using f for the script indexes, and left the i for the context indexes. This separates them and allows the script to go through the first loop on one server context and stay there until it has completed going through the script arrays to completion, before moving on to the next server context.

#!/bin/bash

#   variables
    jss=https://jss.example.com:8443
    user=example
    password=example
    filepath=~/Scripts/
    jssresource=JSSResource/scripts/id/0

#   all xml in one array
    xml=(
        'script1.xml'
        'script2.xml'
        'script3.xml'
        'script4.xml'
        'script5.xml'
    )

#   all context in one array
    context=(
        'test1'
        'test2'
        'test3'
        'test4'
        'test5'
    )

#   loop through context and XML
    /bin/echo "`date`: Loop through context and XML"

    for ((i = 0; i < "${#context[@]}"; i++))

        do

        for ((f = 0; f < "${#xml[@]}"; f++))

            do
                /bin/echo "`date`: POST ${filepath}/${xml[$f]} to ${jss}/${context[$i]}"
                /usr/bin/curl -k -v -u "$user":"$password" "$jss/${context[$i]}/$jssresource" -T "$filepath"/"${xml[$f]}" -X POST

            done

        done

#   exit
    exit 0

I only tested this by commenting out the curl line so I would get the echoes back and it showed up like this in TextWrangler:

Wed Nov 25 14:28:32 EST 2015: Loop through context and XML
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test5

Edit: minor thing, but your filepath variable has a trailing slash in it, so you don't need to include it in the echo line, as its giving you double slashes in the paths as seen in the script output above.

View solution in original post

9 REPLIES 9

mm2270
Legendary Contributor III

I'm not seeing an issue with what you have, though I'm only glancing over it. It looks like it should be iterating through the bash indices in both arrays doing the echo and curl commands for each as you have it. Is it not doing that? If not, what is it you see it doing specifically?

Snickasaurus
Contributor

You could run the script with one of the following to check for errors.

set -x #DEBUG - Display commands and their arguments as they are executed.
set -v #VERBOSE - Display shell input lines as they are read.
set -n #EVALUATE - Check syntax of the script but don't execute.

Just as @mm2270 said your syntax looks good except the date command where you used ` instead of the newer $( ) but that is just the way I like doing it. Either way works.

mm2270
Legendary Contributor III

Ok, looking closer I think I see the issue. Is it that its only copying script1.xml to test1, and then script2.xml to test2, and so on, instead of copying all scripts 1 through 5 up to test1 and then moving on to the next context?

mm2270
Legendary Contributor III

@anverhousseini If the issue is what I mentioned above, the trick is you need to include an additional for loop within the one you have that handles all the items in the scripts array. But you have to specify a different character as a placeholder for the array indices.

I copied/pasted your script into TextWrangler and added this as shown below. Give this a try. Note that I'm using f for the script indexes, and left the i for the context indexes. This separates them and allows the script to go through the first loop on one server context and stay there until it has completed going through the script arrays to completion, before moving on to the next server context.

#!/bin/bash

#   variables
    jss=https://jss.example.com:8443
    user=example
    password=example
    filepath=~/Scripts/
    jssresource=JSSResource/scripts/id/0

#   all xml in one array
    xml=(
        'script1.xml'
        'script2.xml'
        'script3.xml'
        'script4.xml'
        'script5.xml'
    )

#   all context in one array
    context=(
        'test1'
        'test2'
        'test3'
        'test4'
        'test5'
    )

#   loop through context and XML
    /bin/echo "`date`: Loop through context and XML"

    for ((i = 0; i < "${#context[@]}"; i++))

        do

        for ((f = 0; f < "${#xml[@]}"; f++))

            do
                /bin/echo "`date`: POST ${filepath}/${xml[$f]} to ${jss}/${context[$i]}"
                /usr/bin/curl -k -v -u "$user":"$password" "$jss/${context[$i]}/$jssresource" -T "$filepath"/"${xml[$f]}" -X POST

            done

        done

#   exit
    exit 0

I only tested this by commenting out the curl line so I would get the echoes back and it showed up like this in TextWrangler:

Wed Nov 25 14:28:32 EST 2015: Loop through context and XML
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:32 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test1
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test2
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test3
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test4
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script1.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script2.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script3.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script4.xml to https://jss.example.com:8443/test5
Wed Nov 25 14:28:33 EST 2015: POST /Users/mike/Scripts//script5.xml to https://jss.example.com:8443/test5

Edit: minor thing, but your filepath variable has a trailing slash in it, so you don't need to include it in the echo line, as its giving you double slashes in the paths as seen in the script output above.

Snickasaurus
Contributor

I didn't even see that another for loop was missing. I'm done for the day.

*exits stage left

mm2270
Legendary Contributor III

@Snickasaurus Honestly I didn't see it at first myself, so don't feel bad :) Its a holiday weekend coming up (at least here in the US), so that's my excuse and I'm sticking to it.

Snickasaurus
Contributor

nom nom nom turkey nom nom nom

I'm Cajun frying my first turkey this year. Words do no justice as to how excited I am inside. :-)

anverhousseini
Contributor II

@mm2270 & @Snickasaurus You both are heroes for this evening! Works perfectly! I wish you both great thanks giving. We don't know this in switzerland, so I'm still working :)

Snickasaurus
Contributor

@anverhousseini

Mike gets all the credit.

echo "<result>SLOW CLAP</result>"