The way our bash completion string is that is gets user's input and lets virsh completion code do all the work by calling 'virsh complete -- $INPUT". The 'complete' command is a "secret", unlisted command that exists solely for this purpose. After it has done it's part, it prints candidates onto stdout, each candidate on its own line, e.g. like this: # virsh complete -- "net-u" net-undefine net-update net-uuid These strings are then stored into a bash array $A like this: A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null)) This array is then thrown back at bash completion to produce desired output. So far so good. Except, when there is an option with space. For instance: # virsh complete -- start --domain "" uefi\ duplicate uefi Bash interprets that as another array item because by default, Internal Field Separator (IFS) = set of characters that bash uses to split words at, is: space, TAB, newline. We don't want space nor TAB. Therefore, we have to set $IFS when storing 'virsh complete' output into the array. Thanks to Peter who suggested it. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/116 Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- tools/bash-completion/vsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bash-completion/vsh b/tools/bash-completion/vsh index fb38e8616f..bbb25fc3eb 100644 --- a/tools/bash-completion/vsh +++ b/tools/bash-completion/vsh @@ -56,7 +56,7 @@ _vsh_complete() # the name of the command whose arguments are being # completed. # Therefore, we might just run $1. - A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null)) + IFS=$'\n' A=($($1 ${CMDLINE} complete -- "${INPUT[@]}" 2>/dev/null)) COMPREPLY=($(compgen -W "${A[*]%--}" -- ${cur})) __ltrim_colon_completions "$cur" -- 2.26.2