4 ms·
No need for that. In shell the preferred form for "and" and "or" is outside the test, and you always quote anything with a variable reference, like this:
by dwheeler 4y ago
No need for that.
In shell the preferred form for "and" and "or" is outside the test, and you always quote anything with a variable reference, like this:
if [ "$x" = "foo" ] && [ -z "$empty" ] ; then
echo "Worked"
fi
I think the "&&" is easier to read, as well as completely eliminating the problem.
- dataflow 4y agoThat was also discussed in the thread: https://news.ycombinator.com/item?id=26778153 https://news.ycombinator.com/item?id=26778153
- dezgeg 4y agoNot to mention this syntax short-circuits, which is usually desirable.
- cduzz 4y agoOh, shell pet peev #301; shell has "case" as part of the language, and case is way better at string evaluation that the "test" built in case "$x" in (foo) echo Worked ;; esac
- cduzz 4y agoSorry I should have elaborated... "test" or it's other name "[" is a program or a built in. It takes a parameter to tell it what to do. It can evaluate strings, but it can also look at the file system or do a little numeric evaluation. Newer versions in gnuland may even be able to tell you if a unicode glyph is left to right or right to left. It does all this using - or -- prefixed options. test -f /dev/sda will fail (it's a block device not a file) test -f /dev will fail (it's a directory) test -h /usr/bin/[ will succeed on some unices (it's a symbolic link to /usr/bin/test) So -- what does [ "$x" = foo ] (or, more clearly, test "$x" = foo) do if the variable x happens to have "-f" in it? The shell will interpret the " and the $x and hand to the builtin this: [ -x = foo ] (or test -x = foo) Now, the human is waving their hands "that's not what I meant no fair!" but a contract's a contract -- test might look around for a directory entry in the current directory and not find a file named =, or hey, it might, because = is a fair directory entry name. It may then poke at that associated inode and find that = is in fact a file, and return a 0 in the exit status. Or it may say "hey, file existence testing has one paramater and you gave me a filename, =, and another file, foo, what gives? Regardless -- you've got no control over the contents of variable x; that's why you're asking test to look into it for you. You can blorp a thing in front of it to protect yourself from this case, but that's just silly. Test can't do any regular expressions and it does all sorts of other things, so it's taking parameters, it's just a mess. Just use case $x in ... esac. Test is great for other stuff, but string evaluation? It wasn't ever good for it.
- dwheeler 4y agoCase is better at pure string comparisons, but I believe the -x example is wrong. Test is PRIMARILY influenced by the argument count, so [ "$x" = "value" ] always does a string comparison for equality, never anything else.