Bash mapfile array count different

I did the following:

mapfile -t array < <(commands)

where commands will produce new-line separated output.

Then based on the result, if there’s nothing in the array, exit, otherwise continue:

[[ "${#array[@]}" -eq 0 ]] && exit

...

The problem is that the condition is never met. Because when the said commands returns nothing, the ${#array[@]} returns 1 instead of 0.

But it counts correctly if I assign the array as follows:

array=($(commands))

My tests:

$ declare -a array
$ array=($(echo))
$ echo ${#array[@]}
0
$ unset array
$ mapfile -t array < <(echo)
$ echo ${#array[@]}
1

Why?


Initially I used the array=($(commands)) format but shellcheck suggested me to use mapfile instead.

GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Asked By: annahri

||

This is what you get if the command inside the prints nothing:

$ mapfile -t array < <(printf ''); echo "num: ${#array[@]}"; declare -p array
num: 0
declare -a array=()

This is what you get if it prints a single empty line:

$ mapfile -t array < <(echo); echo "num: ${#array[@]}"; declare -p array
num: 1
declare -a array=([0]="")

The empty line produces an empty element, quite appropriately.

If your program produces such empty lines and you can’t stop it, you could remove them with e.g. grep. Or check for the case of a single array element that’s empty.

Remove the empty lines with grep:

$ mapfile -t array < <(echo | grep .); echo "num: ${#array[@]}"; declare -p array
num: 0
declare -a array=()

Check for the empty element:

$ mapfile -t array < <(echo);
$ if [[ "${#array[@]}" = 0 || "${#array[@]}" = 1 && "${array[0]}" = "" ]]; then 
    echo "empty list or only one empty element"; 
 fi
empty list or only one empty element

In

array=($(commands))

it’s different, since the result of the command substitution goes through word splitting, which also removes any trailing whitespace. And splits lines with whitespace in them. (The command substitution itself also removes any trailing newlines, not that it matters here.)

Answered By: ilkkachu
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.