Skip to content
Vidar Holen edited this page Mar 2, 2019 · 12 revisions

Prefer mapfile or read -a to split command output (or quote to avoid splitting).

Problematic code:

array=( $(mycommand) )

Correct code:

If it outputs multiple lines, each of which should be an element:

# For bash 4.x
mapfile -t array < <(mycommand)

# For bash 3.x+
array=()
while IFS='' read -r line; do array+=("$line"); done < <(mycommand)

# For ksh
array=()
mycommand | while IFS="" read -r line; do array+=("$line"); done

If it outputs a line with multiple words (separated by spaces, other delimiters can be chosen with IFS), each of which should be an element:

# For bash
IFS=" " read -r -a array <<< "$(mycommand)"

# For ksh
IFS=" " read -r -A array <<< "$(mycommand)"

If the output should be a single element:

array=( "$(mycommand)" )

Rationale:

You are doing unquoted command expansion in an array. This will invoke the shell's sloppy word splitting and glob expansion.

Instead, prefer explicitly splitting (or not splitting):

  • If you want to split the output into lines or words, use mapfile, read -ra and/or while loops as appropriate.
  • If the command output should become a single array element, quote it.

This prevents the shell from doing unwanted splitting and glob expansion, and therefore avoiding problems with output containing spaces or special characters.

Exceptions:

If you have already taken care (through setting IFS and set -f) to have word splitting work the way you intend, you can ignore this warning.

ShellCheck

Each individual ShellCheck warning has its own wiki page like SC1000. Use GitHub Wiki's "Pages" feature above to find a specific one, or see Checks.

Clone this wiki locally