I found something surprising when I'm writing for some bash script today. I have pinned it down to this minimal example.
[[ a>b ]]; echo $?
Based on my understanding, because there are no spaces around the >
, this should be testing whether the string a>b
is not empty, and should return an error code of 0
. However, the above command echos 1
in both of the bash versions I tested (details below).
I've also tested using the old "good" test
command,
[ a>b ]; echo $?
echos 0
(tests for that the string a
is not empty and creates an empty file b
in my current working directory, apparently >b
is treated as a redirection, which is understandable).
Then I tried a few more other things
[[ b>a ]]; echo $?
echos0
and no file is created.[[ b<a ]]; echo $?
echos1
and no file is created.[[ a<b ]]; echo $?
echos0
and no file is created.[ b>a ]; echo $?
echos0
and creates an empty filea
.[ b<a ]; echo $?
reports an error of missing filea
and echos1
due to that error.[ a<b ]; echo $?
reports an error of missing fileb
and echos1
due to that error.[[ a=b ]]; echo $?
echos0
because it's testing whether the stringa=b
is non-empty as I expected.[ a=b ]; echo $?
echos0
for the same reason.[[ a==b ]]; echo $?
echos0
for the same reason.[ a==b ]; echo $?
echos0
for the same reason.[[ a!=a ]]; echo $?
and[ a!=a ]; echo $?
both echo0
(expected)
So it seems that only the spaces around <
and >
can be omitted in a conditional expression but not =
or ==
or !=
if the intention is to do string comparsion. But why is it designed this way? Also it may be my omission but this does not seem to be documented anywhere in the bash manual.
My original problem is trying to use >
unescaped as part of a pattern in a conditional expression ([[ ... ]]
). I originally thought that as long as I don't surround the >
with spaces I should be able to use it unescaped without issues, because it doesn't make sense (and turns out to be impossible after some testing) to do redirections inside a conditional expression either.
However it turns out that it is not the case. Of course the simple solution is just to escape that >
and write \>
instead but I don't understand why it is required.
Here are the bash versions I used for testing,
GNU bash, version 5.2.2(1)-release (aarch64-unknown-linux-android)
and
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
My experiments are carried out under env -i bash --norc --noprofile
.