Bash Array Tutorial: Declare, Access, Loop, and Modify

March 17, 2026

Bash Array Tutorial: Declare, Access, Loop, and Modify

March 17, 2026

Bash arrays let you store multiple values in a single variable — essential for processing lists of files, command outputs, configuration values, or any collection of data in your scripts. The syntax is more verbose than in Python or JavaScript, but once you know the patterns they're straightforward. This tutorial covers every array operation you'll need: declaration, access, loops, slicing, modification, and associative arrays.

fruits=("apple" "banana" "cherry" "date" "elderberry") [0] [1] [2] [3] [4] apple banana cherry date elder… ${arr[@]} all elements ${arr[*]} single string
Indexed array with 5 elements. [@] expands to separate words; [*] expands to one string.

1. Declaring Arrays

Bash has three ways to create an indexed array:

bash
#!/bin/bash

# Method 1: inline declaration with values
fruits=("apple" "banana" "cherry")

# Method 2: explicit declaration (empty array, add later)
declare -a colors
colors[0]="red"
colors[1]="green"
colors[2]="blue"

# Method 3: capture command output into array
files=($(ls /etc/*.conf))          # NOTE: fails on filenames with spaces
mapfile -t files < <(ls /etc/*.conf)  # safer for filenames with spaces

# Verify array contents
echo "${fruits[@]}"    # apple banana cherry
echo "${#fruits[@]}"   # 3  (number of elements)

2. Accessing Elements

bash
fruits=("apple" "banana" "cherry" "date" "elderberry")

# Access by index (zero-based)
echo "${fruits[0]}"    # apple
echo "${fruits[2]}"    # cherry

# Negative indexing (Bash 4.2+)
echo "${fruits[-1]}"   # elderberry (last element)
echo "${fruits[-2]}"   # date

# All elements — use double quotes to preserve spacing
echo "${fruits[@]}"    # apple banana cherry date elderberry

# Number of elements
echo "${#fruits[@]}"   # 5

# Length of a single element
echo "${#fruits[1]}"   # 6  (length of "banana")

# Slice: elements starting at index 1, take 3
echo "${fruits[@]:1:3}"  # banana cherry date

# All indices
echo "${!fruits[@]}"   # 0 1 2 3 4

3. Looping Over Arrays

bash
fruits=("apple" "banana" "cherry")

# Loop over values (most common)
for fruit in "${fruits[@]}"; do
    echo "Fruit: $fruit"
done

# Loop with index
for i in "${!fruits[@]}"; do
    echo "fruits[$i] = ${fruits[$i]}"
done
# Output:
# fruits[0] = apple
# fruits[1] = banana
# fruits[2] = cherry

# C-style index loop
for (( i=0; i<${#fruits[@]}; i++ )); do
    echo "$i: ${fruits[$i]}"
done

Always quote "${fruits[@]}" with double quotes. Without quotes, elements with spaces split into separate words.

4. Modifying Arrays

fruits=("apple" "banana" "cherry")

# Append one element
fruits+=("date")

# Append multiple elements
fruits+=("elderberry" "fig")

# Modify a specific element
fruits[1]="blueberry"   # replaces "banana"

# Delete an element (leaves a gap — index 2 becomes empty, not removed)
unset fruits[2]
echo "${fruits[@]}"     # apple blueberry date elderberry fig
echo "${!fruits[@]}"    # 0 1 3 4 5  (note: index 2 is gone)

# Reindex after deletion (create new contiguous array)
fruits=("${fruits[@]}")

# Delete entire array
unset fruits

The gap left by unset arr[n] is a common gotcha — the array is now sparse. If you need contiguous indices after deletion, reassign the whole array: arr=("${arr[@]}").

5. Associative Arrays

Associative arrays use string keys instead of numeric indices. Requires Bash 4+.

bash
#!/bin/bash

# Must declare with -A
declare -A config

config["host"]="localhost"
config["port"]="5432"
config["name"]="mydb"

# Access by key
echo "${config["host"]}"    # localhost

# Loop over key-value pairs
for key in "${!config[@]}"; do
    echo "$key = ${config[$key]}"
done

# Check if key exists
if [[ -v config["host"] ]]; then
    echo "host is set"
fi

3 Common Pitfalls

  1. Forgetting quotes${arr[@]} without double quotes splits on spaces. Always use "${arr[@]}".
  2. Using [*] instead of [@]${arr[*]} expands to one string; ${arr[@]} expands to separate words. Use [@] in loops.
  3. Index gaps after unset — deleting elements leaves sparse indices. Reassign with arr=("${arr[@]}") to repack.

For more Bash scripting patterns, see the bash functions guide where arrays are frequently used to pass multiple return values.

Summary

Declare with arr=(val1 val2), access with ${arr[0]}, loop with for x in "${arr[@]}", get length with ${#arr[@]}, and use declare -A for string-keyed maps. Quote [@] expansions consistently and you'll avoid the most common array bugs.