Забудь этот язык как страшный сон, как только сдашь зачёт. Он уродует человеку мозги. По теме: опытным путём установлено, что надо использовать использовать конструкцию [[ -z «$var» ]] && echo «la-la»
Ну, во-первых, [ — это алиас встроенной команды test. У них одинаковые ограничения. [[ — более продвинутая версия.
[ использует для проверки строк на совпадение операторы = и !=. [[ использует ==, != и =~, при этом правый аргумент расценивается как регулярное выражение, а не как строка, если не взят в кавычки.
Собственно, поэтому аргументы, указанные в [[ не подвергаются pathname expansion, то есть
[[ "$a" == "$b"* ]]
будет всегда расцениваться, как «начинается ли то, что лежит в $a с $b?», в то время как
[ "$a" = "$b"* ]
тоже верная конструкция, которая означает «раскрыть $b* до всех соответствующих имён в текущем каталоге и сравнить со строкой из $a». При этом если мы в пустом каталоге сделаем…
Правый аргумент раскрылся во множество строк каждая с именем существующего файла, и это вызвало ошибку, потому что = ожидает только один аргумент после себя.
Операторы > и < в обоих командах сравнивают строки лексически, но [ сравнивает по ASCII, а [[ – используя локаль, которая может быть хоть С, хоть из UTF-8.
Логические операторы просто называются по-разному, [ использует -a и -o, а [[ – && и || соответственно.
Использование [[ оправдано только там, где оно необходимо и необходимость эта обоснована.