Network System Access Solutions

User Tools

Site Tools





For completeness and details on several parameter expansion variants, see the article about parameter expansion and check the notes about arrays.


An array is a way for the coder to collect multiple values (data, text, numbers) under a common name, the name of the array. The specific values are accessible using an index into the array. Thus, the array (in any programming language) is a useful and common data structure.

This is a symbolic (not a real!) view of an array named NAMES, the indexes go from 1 to 4 (technical 0 to 3) here.

 0: Peter
 1: Anna
 2: Greg
 3: Jan

The purpose is clear: If you want the second name, you ask for the index 1 of the array NAME. All your names are in the array NAME, you don't need 4 variables for 4 names, just one variable (the array) which contains many elements.


  • As in C, the array indexes start at 0 (zero)!
  • Multidimensional arrays are not implemented


Bash supports two different indexing methods for arrays:

  • integer numbers (starts at 0)
  • :V4: strings

The indexing by numbers is what was shown above: Every element is indexed by an integer number.

:V4: The indexing by strings is called associative.



When you want to declare an empty array, for later use, you have the following options:

Syntax Description
ARRAY=() Declares an integer indexed array ARRAY and initializes it to be empty. This can also be used to empty an existing array.
ARRAY[0]=XYZ Generally sets the first element of an integer indexed array. If no array ARRAY existed before, it is created.
declare -a ARRAY Declares an integer indexed array ARRAY. An existing array is not initialized.
declare -A ARRAY :V4: Declares an associative array ARRAY. This is the one and only way to create associative arrays.

Storing values

Storing values in arrays is quite as simple as storing values in normal variables.

Syntax Description
ARRAY[N]=VALUE Sets the element N of the integer indexed array ARRAY to VALUE. N can be any valid arithmetic expression. Attention, that means, if you want to index it by a string (like an associative array), this string is evaluated as an arithmetic expression, and most likely evaluated to 0, so you will just set the first element!
ARRAY[STRING]=VALUE :V4: Sets the element indexed by STRING of the associative array ARRAY.
ARRAY=(E1\ E2\ …) Sets the whole array ARRAY to the given list of elements. It's kind of mass-setting the array. The whole array will be overwritten if it exists. As shown above, when the list is empty (ARRAY=()), the whole array will be cleared. :V4: This method obvisually does not use explicit indexes. An associative array can not be set like that! Clearing an associative array using ARRAY=() works.
ARRAY=([X]=E1\ [Y]=E2\ …) Again a kind of mass-setting, but for individual given indexes (here for example X and Y).
ARRAY=([S1]=E1\ [S2]=E2\ …) :V4: Individual mass-setting for associative arrays. The named indexes (here: S1 and S2) are strings.

As of now, arrays can't be exported.

Getting values

Syntax Description
${ARRAY[N]} Expands to the value of the index N in the integer indexed array ARRAY. If N is a negative number, it's treated as the offset from the maximum assigned index - 1 /:V4: 4.2-alpha)
${ARRAY[S]} :V4: Expands to the value of the index S in the associative array ARRAY.
Similar to mass-expanding positional parameters, this expands to all elements. If unquoted, both subscripts * and @ expand to the same result, if quoted, @ expands to all elements individually quoted, * expands to all elements quoted as a whole.
Similar to what this syntax does for the characters of a single string when doing substring expansion, this expands to M elements starting with element N. This way you can mass-expand individual indexes. The rules for quoting and the subscripts * and @ are the same as above for the other mass-expansions.

For clarification: When you use the subscripts @ or * for mass-expanding, then the behaviour is exactly what it is for $@ and $* when mass-expanding the positional parameters. You should read this article to understand what's going on.


Syntax Description
${#ARRAY[N]} Expands to the length of an individual array member at index N (stringlength)
${#ARRAY[STRING]} :V4: Expands to the length of an individual associative array member at index STRING (stringlength)
Expands to the number of elements in ARRAY
Expands to the indexes in ARRAY since BASH 3.0


The unset builtin command is used to destroy (unset) arrays or individual elements of arrays.

Syntax Description
unset ARRAY
unset ARRAY[@]
unset ARRAY[*]
Destroys a complete array
unset ARRAY[N] Destroys the array element at index N
unset ARRAY[STRING] :V4: Destroys the array element of the associative array at index STRING

<note warning> Destroying individual array elements using the syntax above may cause pathname expansion to occur.

Example: You are in a directory with a file named x1, and you want to destroy an array element x[1], with

unset x[1]

then pathname expansion will expand to the filename x1 and break your processing!

Even worse, if nullglob is set, your array/index will disappear.

To avoid this, either disable pathname expansion or quote the array name and index:

unset "x[1]"



Numerical Index

Numerical indexed arrays are easy to understand and easy to use. The Purpose and Indexing chapters above more or less explain all the needed background theory.

Now, some examples and comments for you.

Let's say we have an array SENTENCE which is initialized as follows:

SENTENCE=(Be liberal in what you accept, and conservative in what you send)

Since no special code is there to prevent word splitting (no quotes), every word there will be assigned to an individual array element. When you count the words you see, you should get 12. Now let's see if Bash has the same opinion:

$ echo ${#SENTENCE[@]}

Yes, 12. Fine. You can take this number to walk through the array. Just subtract 1 from the number of elements, and start your walk at 0 (zero):


for ((i = 0; i <= MAX_INDEX; i++)); do
  echo "Element $i: '${SENTENCE[i]}'"

You always have to remember that, it seems newbies have problems sometimes. Please understand that numerical array indexing begins at 0 (zero)!

The method above, walking through an array by just knowing its number of elements, only works for arrays where all elements are set, of course. If one element in the middle is removed, then the calculation is nonsense, because the number of elements doesn't correspond to the highest used index anymore (we call them ”sparse arrays”).

Associative (Bash 4)

Associative arrays (or hash tables) are not much more complicated than numerical indexed arrays. The numerical index value (in Bash a number starting at zero) just is replaced with an arbitrary string:

# declare -A, introduced with Bash 4 to declare an associative array
declare -A SENTENCE

SENTENCE[Begin]="Be liberal in what "
SENTENCE[Middle]="you accept, and conservative "
SENTENCE[End]="in what you send"
SENTENCE["Very end"]="..."

Beware: don't rely on the fact that the elements are ordered in memory like they were declared, it could look like this:

# output from 'set' command
SENTENCE=([End]="in what you send" [Middle]="you accept, and conservative " [Begin]="Be liberal in what " ["Very end"]="..." )

This effectively means, you can get the data back with “${SENTENCE[@]}”, of course (just like with numerical indexing), but you can't rely on a specific order. If you want to store ordered data, or re-order data, go with numerical indexes. For associative arrays, you usually query known index values:

for element in Begin Middle End "Very end"; do
  printf "%s" "${SENTENCE["$element"]}"
printf "\n"

A nice code example: Checking for duplicate files using an associative array indexed with the SHA sum of the files:

# Thanks to Tramp in #bash for the idea and the code

unset flist; declare -A flist;
while read -r sum fname; do 
    if [[ ${flist[$sum]} ]]; then
        printf 'rm -- "%s" # Same as >%s<\n' "$fname" "${flist[$sum]}" 
done <  <(find . -type f -exec sha256sum {} +)  >rmdups
linux/shell/array.txt · Last modified: 2013/05/23 11:36 (external edit)