Bash Arrays

By 

Updated on

6 min read

Working with arrays in Bash scripting

Arrays are one of the most commonly used and fundamental data structures. You can think of an array as a variable that stores multiple values, allowing you to represent and manipulate a group of related data as a single entity.

Bash supports two types of arrays: numerically indexed arrays referenced by integers, and associative arrays referenced by strings (keys). Unlike most programming languages, Bash array elements do not have to be the same data type — an array can contain both strings and numbers. Bash does not support multidimensional arrays.

Numerically indexed arrays can be accessed from the end using negative indices. The index -1 references the last element. Indices do not have to be contiguous.

Info
Some array features are not available in very old Bash versions (for example, the default Bash 3.2 on older macOS systems). Associative arrays and negative indexing require a newer Bash version.

Creating Arrays

Numerically Indexed Arrays

Bash variables are untyped, so any variable can be used as an indexed array without declaring it. To explicitly declare one, use the declare builtin:

sh
declare -a array_name

You can assign elements individually by index:

sh
array_name[0]=value_1
array_name[1]=value_2
array_name[2]=value_3

Or initialize the whole array at once using parentheses, with elements separated by spaces:

sh
array_name=( element_1 element_2 element_3 )

When using this form, indexing starts at zero.

Associative Arrays

Associative arrays use strings as keys instead of integers. Unlike indexed arrays, they must be declared before use:

sh
declare -A array_name

Assign elements individually:

sh
declare -A array_name

array_name[key_foo]=value_foo
array_name[key_bar]=value_bar
array_name[key_xyz]=value_xyz

Or use the inline form:

sh
declare -A array_name=(
  [key_foo]=value_foo
  [key_bar]=value_bar
  [key_xyz]=value_xyz
)

Access Elements

To reference a single element, use the following syntax:

sh
${array_name[index]}
Info
The curly braces ${} delimit the variable name and index expression so Bash parses it correctly.

For example, to print the element at index 1:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

echo ${my_array[1]}
output
Helium

To access all elements, use @ or * as the index:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

echo "${my_array[@]}"
output
Hydrogen Helium Lithium Beryllium

The difference between @ and * matters when the expression is inside double quotes. "${my_array[*]}" expands to a single word with elements separated by spaces. "${my_array[@]}" expands each element as a separate word. Use @ when iterating over array elements to handle values that contain spaces correctly.

To print all keys (indices), add ! before the array name:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

echo "${!my_array[@]}"
output
0 1 2 3

Array Length

To get the number of elements in an array, prefix the array name with #:

sh
${#array_name[@]}

Here is an example:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

echo ${#my_array[@]}
output
4

Loop Through an Array

The for loop is the most common way to iterate over array elements:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

for i in "${my_array[@]}"
do
  echo "$i"
done
output
Hydrogen
Helium
Lithium
Beryllium

To print both keys and values:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

for i in "${!my_array[@]}"
do
  echo "$i" "${my_array[$i]}"
done
output
0 Hydrogen
1 Helium
2 Lithium
3 Beryllium

You can also use a C-style loop with the array length:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

length=${#my_array[@]}

for (( i=0; i < ${length}; i++ ))
do
  echo $i ${my_array[$i]}
done
output
0 Hydrogen
1 Helium
2 Lithium
3 Beryllium

Add Elements

To add an element at a specific index:

sh
my_array[index]="New Element"

To append one or more elements without specifying an index, use the += operator:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

my_array+=( Cobalt Nickel )

echo "${my_array[@]}"
output
Hydrogen Helium Lithium Beryllium Cobalt Nickel

Slice an Array

To extract a portion of an array, use the following syntax:

sh
${array_name[@]:offset:length}
  • offset — the starting index
  • length — the number of elements to return

For example, to get two elements starting at index 1:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

echo "${my_array[@]:1:2}"
output
Helium Lithium

Delete Elements

To remove a single element by index, use unset:

sh
declare -a my_array=( "Hydrogen" "Helium" "Lithium" "Beryllium" )

unset my_array[2]

echo "${my_array[@]}"
output
Hydrogen Helium Beryllium

Note that unset removes the element but does not re-index the array. The index gap remains.

To delete the entire array:

sh
unset my_array

Quick Reference

For a printable quick reference, see the bash cheatsheet .

TaskSyntax
Declare indexed arraydeclare -a arr
Declare associative arraydeclare -A arr
Initialize arrayarr=( a b c )
Access element${arr[index]}
Access all elements"${arr[@]}"
Access all keys"${!arr[@]}"
Array length${#arr[@]}
Append elementsarr+=( x y )
Slice array${arr[@]:offset:length}
Delete elementunset arr[index]
Delete entire arrayunset arr
Last element${arr[-1]}

FAQ

What is the difference between @ and * when accessing all elements?
Both expand to all array elements, but the behavior differs inside double quotes. "${arr[@]}" expands each element as a separate word, which correctly handles elements containing spaces. "${arr[*]}" expands to a single string with elements joined by the first character of IFS (usually a space). Always use @ when iterating.

How do I check if a Bash array is empty?
Check the length: [[ ${#my_array[@]} -eq 0 ]]. In a script:

sh
if [[ ${#my_array[@]} -eq 0 ]]; then
  echo "Array is empty"
fi

How do I check if a value exists in an array?
Loop through the array and compare each element :

sh
for i in "${my_array[@]}"; do
  [[ "$i" == "Helium" ]] && echo "Found" && break
done

Why does unset leave a gap in the array index?
unset arr[2] removes the element at index 2 but does not shift the remaining elements. The index 2 simply becomes unset. To re-index, reassign: arr=( "${arr[@]}" ).

Can Bash arrays hold arrays as elements?
No. Bash does not support nested or multidimensional arrays. To simulate a 2D structure, use naming conventions such as arr_0_0, arr_0_1, or use associative arrays with compound keys like arr[0,1].

Conclusion

Bash arrays store multiple values in a single variable. Use indexed arrays for ordered lists and associative arrays for key-value pairs. The [@] expansion, ${#arr[@]} for length, += for appending, and unset for deletion are the core operations you will use most often.

For more on Bash scripting, see the guides on for loops and if/else statements .

If you have any questions, feel free to leave a comment below.

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page