Your workaround is effective, as long as the string stored in
$A is not an operator that
test recognizes - simply adding a space is sufficient, as you've discovered.
Surely the "greater than" should be interpreted as just a string? It works with '> ' after all.
No, the content of
$A is not interpreted as just a string. (If you wanted that, you'd have to use
[[ instead, which is parsed in a special context, more like you'd expect from traditional programming languages.)
test) is a builtin (also exists as an external utility on most systems) and is therefore parsed with command syntax, which means:
- the shell performs its expansions first -
$Areferences are replaced with the content of the variable in this case.
- the result is then passed to
Thus, from the perspective of
[, it doesn't matter whether or not the operator it ultimately sees -
> in your example - came from a literal or was stored in a variable.
But note that whitespace matters: passing
> (no spaces) is interpreted as an operator;
>, by contrast,
> is not - because that exact literal is more than just the operator.
The bottom line is:
- The bash-completion script you're using is not robust.
- As @chepner states in a comment on the question, POSIX recommends not using
-ato avoid the ambiguity you encountered (emphasis mine):
The XSI extensions specifying the -a and -o binary primaries and the '(' and ')' operators have been marked obsolescent. (Many expressions using them are ambiguously defined by the grammar depending on the specific expressions being evaluated.)
Specifically, using separate
[ ... ]expressions joined with
-o) solves the problem:
[ -n "$BASH_VERSION" ] && [ -n "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
Or, more simply, taking advantage of a non-empty string evaluating to true:
[ "$BASH_VERSION" ] && [ "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
Note that while
-o introduce ambiguities, they are not a security concern - you cannot inject arbitrary code through their use.