Looping through arrays in bash with a thorough syntax explanation of each part

some rainbow bash for the kewl colors

A for loop is a relatively simple concept, but I wanted to break down the syntax here because under the hood, bash is very much, and I cannot exmphasize this enough, not C. I do try to see what’s happening under the hood though so that when I copy paste from StackOverflow and it doesn’t work, I can actually troubleshoot.

You can loop through arrays in bash like this

If you want to iterate through pairs, an easy way to do that would be something like this:

Basically, you can reuse the same index to access both arrays,

Lets break this first one down for simplicity:

Normally parenthesis in bash indicate what’s called a “subshell”.

To quote the “man bash” page:

This is actually quite portable and not specific to just bash though. The POSIX Shell Command Language spec has the following description for the (compound-list) syntax:

Execute compound-list in a subshell environment; see Shell Execution Environment. Variable assignments and built-in commands that affect the environment shall not remain in effect after the list finishes.

so basically, you’ve invoked a little subshell here, it’s kind of like calling a little subroutine or something like that, in the sense that it returns something just like a subroutine,

Let’s take a look at this

Grouping Commands

The format for grouping commands is as follows:

( compound-list ) Execute compound-list in a subshell environment; see Shell Execution Environment. Variable assignments and built-in commands that affect the environment shall not remain in effect after the list finishes.

If a character sequence beginning with “((“ would be parsed by the shell as an arithmetic expansion if preceded by a ‘$’, shells which implement an extension whereby “((expression))” is evaluated as an arithmetic expression may treat the “((“ as introducing as an arithmetic evaluation instead of a grouping command. A conforming application shall ensure that it separates the two leading ‘(‘ characters with white space to prevent the shell from performing an arithmetic evaluation.

{ compound-list ; } Execute compound-list in the current process environment. The semicolon shown here is an example of a control operator delimiting the } reserved word. Other delimiters are possible, as shown in Shell Grammar; a <newline> is frequently used.

so there are basically two types of compound lists, one you execute in a subshell environment, and another you execute in the current process environment.


  • $() is command substitution,
  • ${} is how we get the value of a variable
  • () is a subshell that executes and then returns a value.

Variables in a subshell are not visible outside the block of code in the subshell. They are not accessible to the parent process, to the shell that launched the subshell. These are, in effect, local variables.

This means that you could declare local variables and do local computations in that subshell to compute your list if you wanted to

  • { ;} is for a compound lists in the current shell environment, I am not sure yet what this would be used for, perhaps I can cover it in another article.

Ok, next line of the script:

so here we declare the for loop, very nice,

  • ! in case is used for “indirect referencing”. (unlike it’s usual use as a negation operator for inverting a bool).

Documentation here indicates:

Indirect referencing in Bash is a multi-step process. First, take the name of a variable: varname. Then, reference it: $varname. Then, reference the reference: $$varname. Then, escape the first $: \$$varname. Finally, force a reevaluation of the expression and assign it: eval newvar=\$$varname.

Of what practical use is indirect referencing of variables? It gives Bash a little of the functionality of pointers in C, for instance, in table lookup. And, it also has some other very interesting applications. . . .t

so there we have it, we reference a reference and then re-evaluate it to get the behavior of a pointer in an array.

  • @ is for iterating through positional arguments. You can think of it like an iterator just bouncing down a list that is passed to it. It sees the arguments passed to it as separate words.
  • ; is a command separator
  • do keyword is for looping over the positional paramters (in this case the contents of the array we are passing in) do is also necessary in while and until loops

Okay, let’s go to the next line

  • ${} is for getting the value of a variable
  • [] — single brackets are for array indices
  • echo is for printing out to the command line

Ok, let’s go to the next line:

  • done keyword just ends the for loop

Alright, we should have a much better understanding now of what the bash is actually doing, that’s great!

Research and Development | Dev Ops | Software Engineer | Topaz Labs

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store