Silversonic
Silversonic

Reputation: 1329

Why does the test command need escaping for ">"?

From $ help test:

test: test [expr]

Evaluate conditional expression.

Exits with a status of 0 (true) or 1 (false) depending on the evaluation of EXPR. Expressions may be unary or binary. Unary expressions are often used to examine the status of a file. There are string operators and numeric comparison operators as well.

I'm a bit confused as to what expr can supposedly contain. The help page for test indicates that it is a conditional expression, consisting of file, string or numeric operators. So how does the string comparison operator cause unwanted file re-direction?

$ [ "a" > "b" ]
$ ls -la 
-rw-rw-r--  1 user user     0 May 28 17:22 b

I understand that to prevent re-direction I need to escape >, but I'm confused why. It's not like I can place any command as the expr:

$ [ echo "hello" ] 
bash: [: echo: unary operator expected

As far as I can make out from the help text test only evaluates pre-defined operators in expr - file re-direction not being one of them. test/[ are only meant to evaluate conditional expressions - I'm limited to only the operators that test accepts, and arguments it accepts with them.

(For comparison, with the following built-in there is no confusion as to what > means and no escaping is necessary):

$ echo $[2>1]
1

So what is interpreting > as re-direction meaning escaping is needed?

Upvotes: 1

Views: 85

Answers (1)

chepner
chepner

Reputation: 531165

test is an ordinary command, not special syntax, and as such undergoes the same processing as any other command.

[ "a" > "b" ]

is just a (overly) clever synonym for

test "a" > "b"

and so > is interpreted as an output redirection before the arguments to test are identified. The exact same command can be written

[ "a" ] > "b"

To prevent the shell from recognizing > as the redirection operator, it must be escaped.

[ "a" \> "b" ]  # or [ "a" ">" "b" ]

The other example you gave, $[2>1] is special syntax (not simply a built-in command), and so doesn't undergo the same processing. $[...] is an obsolete, no-longer-documented, form of arithmetic expansion, equivalent to $((2>1)). As special syntax, the shell parses the contents of $[...] different than it would an ordinary command.


A note on ]. test is a regular command, and so is responsible for interpreting its arguments as it sees fit. The following are all syntactically correct:

  1. test a \> b
  2. test a \> b ]
  3. [ a \> b
  4. [ a \> b ]

However, only 1 and 4 are semantically correct. When used as [, the final argument must be ] to maintain the illusion of [ ... ] as merely "grouping" the expression.

$ [ a \> b
bash: [: missing `]'

When used as test, ] is not a valid part of an expression at all, and must be omitted.

$ test a \> b ]
bash: test: too many arguments

Upvotes: 4

Related Questions