I actually found a duplicate (second) while writing this question...
Adding a letter prefix is actually a workaround for some (mostly legacy) implementations of the test
(aka [
) utility, within a shell context. Such as when myvar
is equal to -o
, -n
or (
, which in some cases could be confused with an operator (and that would be avoided by prefixing with say x
). By design of how the shell is working, the test
command has no way to be sure that, when it receives its arguments, a given particular arg is either an operator or an operand.
My test(1)
manual warns:
NOTE: Binary -a and -o are inherently ambiguous. Use 'test EXPR1 && test EXPR2' or 'test EXPR1 || test EXPR2' instead.
So, today, my dash sh
implementation is like this:
b="("
test "AAA" = "AAA" -a "$b" = "BBB"
# yields "test: closing paren expected"
could be avoided with x"$b" = x"BBB"
or with two tests like test "AAA" = "AAA" && test "$b" = "BBB"
.
a='='
b=x
test -n "$a" -a -n "$b"
# yields test: -a: unexpected operator
this shows ambiguity which could be avoided by using "$empty" = ""
(rather than -n
) if -a
or -o
is in use, and thus using prefixing (x"$empty" = x
) for parenthesis issues in this case.
Usually, nowadays:
- doing only one
test
is safe (max 3 arguments, not using -o
nor -a
) and doesn't require this workaround (except old/buggy implementation),
- Using
-o
/-a
, especially when operands may look like operators or parenthesis (
/)
can be ambiguous and buggy, and this workaround can help.
Note that for safety you should always quote "$variables"
passed to test
, so that they are always interpreted as one argument, even if they contain spaces.
For more details, Stéphane Chazelas wrote a quite comprehensive answer to this question that I encourage you to read. I'm still posting this question & answer so that more cues point to the information that would be easier to find.
Today implementations corrected many legacy implementation problems leading to ambiguous behaviour, so that on those, prefixing with say x
for tests not using -o
or -a
is often unnecessary.