On Thu, Aug 05, 2021 at 10:38:47AM +0200, to...@tuxteam.de wrote: > On Thu, Aug 05, 2021 at 09:26:35AM +0100, Tixy wrote: > > ; has no special meaning inside "". The expression is true because > > there is only a single non-null argument between the [ ]
Precisely. But you're probably not explaining it in a way the OP will understand. Let's come back to that in a moment. > echo A="0 ; " > => A=0 ; I'm not sure that helps much. > echo -n '<' ; echo -n A="0 ; " ; echo '>' > => <A=0 ; > Why not simply echo "A=<$A>" ? (Or printf, to be safer, but we'll save that for a different email. The OP doesn't seem able to absorb too many concepts at once.) Now, as promised, How The Test Command Works. The test command evolved over time. There are several different original versions with slightly different behaviors, and even modern shells offer some extensions to the basic standard. In order to make everything consistent, POSIX decreed that test shall work as follows: The first thing it does is *COUNT* the number of arguments that it receives. It is impossible to overstate the importance of this. No matter how much you think your test command looks like it should do XYZ, it's the number of arguments that determines what it actually does. As Tixy said, when you have [ A="foo" ] you are passing *one* argument to test. (Two arguments to the [ form, but the final ] argument gets removed, so in the end, it's one argument that actually counts.) When test is given one argument, what it does is check the *length* of that argument. If the length is 0, the expression is treated as "false", and test exits with status 1 (false/failure). Otherwise, if the length is not 0, it's treated as "true", and test exits with status 0 (true/success). It doesn't matter *what* the string is. All of the following generate a "true" result: test foobar test true test false test 0 test 1 test A=B test 2+2=5 test 'your mother was a hamster' test "$a=$b" It doesn't matter what the argument is, as long as it's not the empty string. In that last example, it doesn't even matter what $a and $b expand to. We're guaranteed there's at least an = sign in between them, so we know it will never be an empty string. When test is given *two* arguments, there are two valid forms that it will look for: test ! somestring test -? something That is, the first argument must be either a literal exclamation point, or it must be a unary test operator which is spelled with a hyphen and then some letter (-e or -d or -x, etc.). If the first argument isn't either of those, the result is "unspecified". It will probably be an error, unless your shell overrides it for some reason. unicorn:~$ test one two bash: test: one: unary operator expected If the first argument is ! then it simply does the reverse of the one-argument check. It looks at the length of the second argument. If the second argument is the empty string, test exits with status 0 (success/true). If the second argument is *not* the empty string, it exits with status 1 (failure/false). If the first argument is one of the unary operators, such as -d, then the corresponding test is performed on the second argument. In the case of -d, it means "check whether the second argument is a directory". And so on. There are also 3-argument and 4-argument forme, but I'm not going to cover them here, because this is already long enough, and I'm basically just repeating the POSIX man page with extra details and examples. If you want to read the official documentation, it's at https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html or if you prefer, you can install the manpages-posix package, and then run "man 1posix test". So, what does all of this actually mean? It means you *cannot* omit the whitespace when you write your test (or [) commands. These are correct: test "$a" = b [ "$a" = b ] These are *not* correct: test "$a"=b [ "$a"=b ] ["$a" = b] ["$a"=b] And so on. See also <https://mywiki.wooledge.org/BashPitfalls#pf10>, and the pitfall after that, or for bonus credit, the entire BashPitfalls page.