Linux Basics: Read Text with Bash read and mapfile
Preserve spaces, split a simple record, or load a short list into an array. Choose the input method that matches your text format.
These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. No packages or administrator access are needed.
Prepare a scratch directory
You need Bash, a text editor, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this scratch directory before running its command. Calling bash explicitly avoids changing executable permissions.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Preserve lines and a missing final newline
Save this as read-lines.sh:
#!/usr/bin/env bash
count=0
while IFS= read -r line || [[ -n "$line" ]]; do
((count += 1))
printf '%d: <%s>\n' "$count" "$line"
done < <(printf '%s\n' ' keep spaces ' 'C:\tmp'; printf '%s' 'last line')
printf 'Lines: %d\n' "$count"Run it:
bash read-lines.shOutput:
1: < keep spaces >
2: <C:\tmp>
3: <last line>
Lines: 3Empty IFS keeps surrounding whitespace; -r preserves backslashes. The extra test processes a final nonempty line when EOF arrives without a newline. Process substitution feeds the loop without running the loop in a pipeline subshell.
2. Split a controlled delimiter format
Save this as read-fields.sh:
#!/usr/bin/env bash
IFS=: read -r service port < <(printf '%s\n' 'preview:8080')
printf 'Service: %s\nPort: %s\n' "$service" "$port"Run it:
bash read-fields.shOutput:
Service: preview
Port: 8080Here IFS=: applies to this read. The last variable receives the remaining fields, so this is appropriate for a controlled two-field format. It is not a CSV parser and does not understand quoted separators.
3. Load a small list into an array
Save this as mapfile-list.sh:
#!/usr/bin/env bash
mapfile -t tasks < <(printf '%s\n' 'review draft' 'run tests' 'publish preview')
printf 'Tasks: %d\n' "${#tasks[@]}"
for index in "${!tasks[@]}"; do
printf '%d. %s\n' "$((index + 1))" "${tasks[index]}"
doneRun it:
bash mapfile-list.shOutput:
Tasks: 3
1. review draft
2. run tests
3. publish previewThe -t flag removes each terminating newline. Quoted array expansions preserve spaces in task names. mapfile requires Bash 4 or newer and stores the list in memory; use a read loop for a large stream.
Clean up
In the same terminal, remove only the example files, return to your original directory, and remove the empty scratch directory:
rm -- read-lines.sh read-fields.sh mapfile-list.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirReference
See the GNU Bash manual: Bash Builtins for the relevant shell behavior. The installed Bash help command also documents these builtins.
Acknowledgements
This post was created with assistance from AI.