8

I have an array of paths to files which each have several lines of text. I'd like to produce an array that is populated with the first line of each file processed like so:

# this.txt first line is [Test this]
# another.txt first line is [Test another]
paths=(
  ./this/path/this.txt
  ./another/path/another.txt
)

for i in ${paths[@]}; do
  read -r line < $i
  lines+=$line
done

At most I've only gotten one value in my array. I can't seem to get the array I'm looking for out of the for loop. I've tried many variations and having a hard time figuring out where I'm going wrong.

2 Answers 2

11

You wanted

lines+=("$line")

+=WORD is string concatenation (or addition). A compound assignment +=(...) appends the values to the array.

You probably also want to quote all your variable expansions here - the line definitely needs it if the line might contain whitespace, but you could have issues elsewhere as well.

1
  • Thanks, it makes sense now why in some of my attempts it looked like the result was a mix of the two lines.
    – dimmech
    Commented Feb 4, 2019 at 2:57
4

In Bash you can also read lines into an array directly. If you select the current array length ${#lines[@]} as the insertion index, you can append to it:

for i in "${paths[@]}"; do
    mapfile -t -n 1 -O ${#lines[@]} lines < "$i"
done

Synopsis excerpt

mapfile mapfile [-n count] [-O origin] [-t] [array]

Read lines from the standard input into the indexed array variable array […]. Options, if supplied, have the following meanings:

  • -n: Copy at most count lines. If count is 0, all lines are copied.

  • -O: Begin assigning to array at index origin. The default index is 0.

  • -t: Remove a trailing newline from each line read.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .