diff --git a/SC2207.md b/SC2207.md new file mode 100644 index 0000000..46428c5 --- /dev/null +++ b/SC2207.md @@ -0,0 +1,50 @@ +## Prefer mapfile or read -a to split command output (or quote to avoid splitting). + +### Problematic code: + +```sh +array=( $(mycommand) ) +``` + +### Correct code: + +If the output should be a single element: + +```sh +array=( "$(mycommand)" ) +``` + +If it outputs multiple lines, each of which should be an element: + +```sh +# For bash +mapfile -t array < <(mycommand) + +# For ksh +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: + +```sh +# For bash +IFS=" " read -r -a array <<< "$(mycommand)" + +# For ksh +IFS=" " read -r -A 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 the command output should become a single array element, quote it. +* If you want to split the output into lines or words, use `mapfile`, `read -ra` and/or `while` loops as appropriate. + +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. \ No newline at end of file