I'm trying to write bash script, which will automatically read all file names in current and custom directories, then apply new created docker image' names to finded yml files via kubectl, then read from two arrays image names and full registry names:

declare -a IMG_ARRAY=`docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | sed ':a;N;$!ba;s/\n/ /g'`
declare -a IMG_NAME=`docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | awk -F'/' '{print $3}' | cut -f1 -d"." | sed ':a;N;$!ba;s/\n/ /g'`

IFS=' ' read -r -a array <<< "$IMG_NAME"
for element in "${array[@]}"
     kubectl set image deployment/$IMG_NAME $IMG_NAME=$IMG_ARRAY --record
     kubectl rollout status deployment/$IMG_NAME

Both arrays has same number of indexes. My loop should take first indexes from IMG_NAME and put into kubectl commands for every array index. For now it is taking whole array....

  • It would be easier to help if you would show the output of docker images as a separate code block. – Bodo Jan 17 '19 at 12:33
  • IMG_NAME: asset_dev2 omnibus_dev2 saferwatch_dev2 stripe_dev2 organization_dev2 register_dev2 – user37033 Jan 17 '19 at 12:48
  • IMG_ARRAY: registry/lsengine_dev2 registry/loadselect_dev2 registry/invoice_dev2 ... – user37033 Jan 17 '19 at 12:49
  • I would prefer to see a separate code block that shows example output of docker images without your post-processing. I want to see the output lines, not what you have combined into variables IMG_NAME and IMG_ARRAY – Bodo Jan 17 '19 at 12:59
declare -a IMG_ARRAY=`...`

This doesn't create much of an array, all the output from the command substitution is assigned to element zero of the array. The actual array assignment syntax is name=(elem1 elem2 ... ), i.e. with parenthesis and the elements as distinct words.

You could use word splitting to separate the output to elements, but that still requires the parens, and you're subject to IFS and globbing. declare -a aaa=( $(echo foo bar) ) creates the two elements foo and bar. Note that it splits on the space between the words, not just on newlines.

Using mapfile/readarray is probably better here, since it's explicitly made for reading lines to an array. The command line help text (help mapfile) describes this:

mapfile: mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
    Read lines from the standard input into an indexed array variable.

    Read lines from the standard input into the indexed array variable ARRAY, or
    from file descriptor FD if the -u option is supplied.  The variable MAPFILE
    is the default ARRAY.

My understanding is that you want to have the processed output of docker images in two arrays where every array element corresponds to a line of the processed output.

This script is untested because I neither know the output of docker images nor do I know the command syntax for kubectl.

mapfile -t IMG_ARRAY < <(docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | sed ':a;N;$!ba;s/\n/ /g')
mapfile -t IMG_NAME < <(docker images | awk '/dev2/ && /latest/' | awk '{print $1}' | awk -F'/' '{print $3}' | cut -f1 -d"." | sed ':a;N;$!ba;s/\n/ /g')


for (( i=0; i<$(( $total )); i++ ))
     kubectl set image deployment/$IMG_NAME[$i] $IMG_NAME[$i]=$IMG_ARRAY[$i] --record
     kubectl rollout status deployment/$IMG_NAME[i]

See https://www.cyberciti.biz/faq/bash-iterate-array/ and https://mywiki.wooledge.org/BashFAQ/005 for explanations.

Instead of


for (( i=0; i<$(( $total )); i++ ))

you can also use

for i in ${!IMG_NAME[@]}

see https://stackoverflow.com/questions/6723426/looping-over-arrays-printing-both-index-and-value

  • You could also use array indirection to loop over the indices directly for i in ${!arr[@]} I think – steeldriver Jan 17 '19 at 13:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.