← Back to Bash Course | Chapter 6: Arrays | Lesson 10 of 10

Reading Command Output Into an Array

Bash can capture a command's output directly into an array, one line per element, without you having to manually loop and append each line yourself.

mapfile / readarray Basics

mapfile -t arr reads standard input line by line and stores each line as one element of arr, with -t stripping the trailing newline from each. This is the cleanest way to turn multi-line text into an array without manual looping.

Example: mapfile / readarray Basics

bash
#!/bin/bash
data=$'apple\nbanana\ncherry'
mapfile -t fruits <<< "$data"
echo "Element count: ${#fruits[@]}"
echo "Second fruit: ${fruits[1]}"

readarray Is the Same as mapfile

readarray is exactly the same builtin as mapfile, just under an alternate name -- the two are fully interchangeable in every script. Some scripts use one name for stylistic reasons, but there is no functional difference.

Example: readarray Is the Same as mapfile

bash
#!/bin/bash
printf "line one\nline two\nline three\n" > lines.txt
readarray -t lines < lines.txt
for line in "${lines[@]}"; do
    echo "Read: $line"
done

Why -t Matters

Without the -t flag, mapfile/readarray keeps the trailing newline character attached to the end of every captured element, which can cause subtle bugs when comparing or displaying those values later. Using -t strips it, giving clean line content.

Example: Why -t Matters

bash
#!/bin/bash
data=$'first\nsecond'
mapfile -t clean_lines <<< "$data"
mapfile raw_lines <<< "$data"
echo "Clean (with -t): [${clean_lines[0]}]"
echo "Raw (without -t): [${raw_lines[0]}]"

read -a for Splitting a Single Line

read -a arr splits one line of input into array elements based on IFS (whitespace by default), which is different from mapfile's job of turning multiple lines into multiple elements. This is handy for parsing a single space-separated line of fields.

Example: read -a for Splitting a Single Line

bash
#!/bin/bash
read -a fields <<< "red green blue"
echo "Number of fields: ${#fields[@]}"
echo "Second field: ${fields[1]}"
Common Mistakes
  1. Using arr=($(command)) and assuming each line becomes one element; that form actually word-splits on all whitespace (not just newlines), so a line with multiple words gets broken into multiple array elements.
  2. Forgetting mapfile/readarray (they are the same command, readarray is an alias) are Bash 4.0+ features and won't work on very old Bash or on sh.
  3. Not using -t with mapfile/readarray, which leaves the trailing newline character attached to the end of every captured element.
Chapter Summary
  • mapfile -t arr <<< "$data" (or < file) reads input line by line directly into an array, one element per line.
  • readarray is simply another name for the exact same builtin as mapfile -- they are fully interchangeable.
  • The -t flag strips the trailing newline from each line before storing it as an element -- almost always what you want.
  • read -a arr <<< "$line" splits a single line into an array by whitespace (using IFS), which is a different use case from reading multiple lines.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.