Bash Mapfile and Readarray
Mapfile reads lines into an array. Each line becomes one array item.
Read a file into an array
The printf line creates the file first. Mapfile reads it into colors, and the output shows the second colour and the count.
printf 'red\ngreen\nblue\n' > colors.txt
mapfile -t colors < colors.txt
echo "${colors[1]}"
echo "${#colors[@]}"Count callback runs
The callback runs once per 2 lines. Six lines give three callback runs, and the count proves it.
printf 'one\ntwo\nthree\nfour\nfive\nsix\n' > numbers.txt
n=0
ticks() { ((n++)); }
mapfile -t -C ticks -c 2 lines < numbers.txt
echo "lines: ${#lines[@]}"
echo "callbacks: $n"The last line without a newline
The file has no newline after three. Mapfile keeps all three lines, while the plain while loop keeps only two.
printf 'one\ntwo\nthree' > lines.txt
mapfile -t kept < lines.txt
while IFS= read -r line; do
dropped+=("$line")
done < lines.txt
echo "${#kept[@]}"
echo "${kept[2]}"
echo "${#dropped[@]}"Example
printf 'ada\ngrace\nlinus\nada\n' > names.txt
mapfile -t names < names.txt
echo "count: ${#names[@]}"
echo "first: ${names[0]}"
echo "last: ${names[-1]}"Key points
- mapfile -t: mapfile -t lines reads lines and drops the newline at each line end.
- readarray: readarray is the same command under a second name.
- Callback: mapfile -C ticks -c 2 runs ticks after every 2 lines read.
- Callback count: a callback that adds one to a counter counts how many times it ran.
- Input file: mapfile reads from a file with <, as in mapfile -t lines < names.txt.
- Last line: mapfile keeps a last line that has no newline at its end.
- While-read loop: a plain while read loop drops that last line, because read fails at the missing newline.
In this example, the printf line creates a file with four names. Mapfile reads the file into the names array. The echoes print the count, the first name, and the last name.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does the -t flag do in mapfile -t lines < names.txt?