Readarray with preppended or appended values in Bash

Viewed 563

In Bash if I want to get a list of all available keyboard layouts but prepend my own keyboard layouts I can do:

readarray -t layouts < <(localectl list-x11-keymap-layouts)
layouts=("custom1" "custom2" "${kb_layouts[@]}")

If I want to append I can do:

readarray -t layouts < <(localectl list-x11-keymap-layouts)
layouts=("${kb_layouts[@]}" "custom1" "custom2")

Is it possible to achieve the same in a single line, in the readarray command?

2 Answers

You can use the -O option to mapfile/readarray to specify a starting index. So

declare -a layouts=(custom1 custom2)
readarray -t -O"${#layouts[@]}" layouts < <(localectl list-x11-keymap-layouts)

will add the lines of the command starting after the existing values in the array instead of overwriting the existing contents.

You can append multiple values at once to an existing array with +=(...):

readarray -t layouts < <(localectl list-x11-keymap-layouts)
layouts+=(custom1 custom2)

Since the process substitution output <(..) is replaced by a FIFO for the processes to consume from, you can add more commands of choice inside. E.g. to append "custom1" "custom2" you just need to do

readarray -t layouts < <(
  localectl list-x11-keymap-layouts; 
  printf '%s\n' "custom1" "custom2" )

This creates one FIFO with contents from both the localectl output and printf output, so that readarray can read them as just another unique non-null lines. For prepend operation, have the same with printf output followed by localectl output.

Related