373

This script is getting an error:

elif [ $operation = "man" ]; then
    if [ $aug1 = "add" ]; then         # <- Line 75
    echo "Man Page for: add"
    echo ""
    echo "Syntax: add [number 1] [number 2]"
    echo ""
    echo "Description:"
    echo "Add two different numbers together."
    echo ""
    echo "Info:"
    echo "Added in v1.0"
    echo ""
elif [ -z $aug1 ]; then
    echo "Please specify a command to read the man page."
else
    echo "There is no manual page for that command."
fi

I get this error:

calc_1.2: line 75: [: =: unary operator expected
4
  • 5
    I think your if statement on line 75 needs a fi.
    – Steve
    Commented Nov 29, 2012 at 2:31
  • 9
    If in doubt, quote vars.
    – koola
    Commented Nov 29, 2012 at 10:47
  • 14
    @koola, 'always' quote vars. Commented Sep 4, 2014 at 12:20
  • Note that this error can occur if $aug1 is misspelt i.e. not declared anywhere.
    – Owl
    Commented Jun 14, 2023 at 18:39

6 Answers 6

793

If you know you're always going to use Bash, it's much easier to always use the double bracket conditional compound command [[ ... ]], instead of the POSIX-compatible single bracket version [ ... ]. Inside a [[ ... ]] compound, word-splitting and pathname expansion are not applied to words, so you can rely on

if [[ $aug1 == "and" ]];

to compare the value of $aug1 with the string and.

If you use [ ... ], you always need to remember to double quote variables like this:

if [ "$aug1" = "and" ];

If you don't quote the variable expansion and the variable is undefined or empty, it vanishes from the scene of the crime, leaving only

if [ = "and" ];

which is not a valid syntax. (It would also fail with a different error message if $aug1 included white space or shell metacharacters.)

The modern [[ operator has lots of other nice features, including regular expression matching.

5
  • 12
    "modern"? Hasn't [[ always been in bash? It has been in Korn shell for over twenty years, and pre-dates bash. (I know what you mean though)
    – cdarke
    Commented Nov 29, 2012 at 9:04
  • @cdarke Fwiw, per page 113 in the 3rd Edition of Learning the Bash Shell, "[[ .. ]] is not available in versions of bash prior to 2.05." In the online pdf from doc.lagout.org, it's on page 326!
    – spen.smith
    Commented Jul 31, 2020 at 7:18
  • 3
    @spen.smith: according to the Bash FAQ, [[ was added to Bash in v2.02 (1998), based on the ksh feature available since the 1980s. In 2012, when cdarke wrote that comment, it was already reasonable to say that it was "in Korn shell for over 20 years." My use of the word "modern" in 2012 was certainly questionable; today, it would be ridiculous. But then, there are still programmers who insist that a C standard published 21 years ago is too modern to use :-)
    – rici
    Commented Jul 31, 2020 at 19:11
  • 2
    Ah that's super interesting. Haha! Thanks for the correction.
    – spen.smith
    Commented Jul 31, 2020 at 19:15
  • 2
    @timo: yes, it will work. Many people prefer to quote "$aug1" although it is not necessary.
    – rici
    Commented Jun 15, 2021 at 16:08
55

It took me a while to find this, but note that if you have a spacing error, you will also get the same error:

[: =: unary operator expected

Correct:

if [ "$APP_ENV" = "staging" ]

vs

if ["$APP_ENV" = "staging" ]

As always, setting -x debug variable helps to find these:

set -x
1
  • 4
    Someone bequeathed this bug to me in a build script. Saved me some time, thanks!
    – Kyle
    Commented Aug 1, 2018 at 19:05
8

Try assigning a value to $aug1 before use it in if[] statements; the error message will disappear afterwards.

1

Make sure that when comparing a variable like $operation using string comparison you do not leave the possibility that $operation returns an empty string if you use the POSIX approach (single bracket).

Both [ $operation == "man"] and [ "" == "man" ] return the same error: [: ==: unary operator expected

Also, you shouldn't use the = operator unless you double bracket, as stated above.

Reference: https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

0

This error can also occur reading numerical input that could possibly be blank (to accept a default option).

The solution is to structure the if statement with multiple conditions & test for an empty variable first.

For example:

# sanitise input
var=$(echo $ans | tr -cd "[:digit:]")

if [ -z "$var" ] || [ "$var" -lt 1 ]; then
   do_something
fi

I had to solve this unary operator expected issue in remove_old_pkgs() of the helper script abk for Arch Sign Modules.

See also 6.4 Bash Conditional Expressions

4
-15

You can also set a default value for the variable, so you don't need to use two "[", which amounts to two processes ("[" is actually a program) instead of one.

It goes by this syntax: ${VARIABLE:-default}.

The whole thing has to be thought in such a way that this "default" value is something distinct from a "valid" value/content.

If that's not possible for some reason you probably need to add a step like checking if there's a value at all, along the lines of "if [ -z $VARIABLE ] ; then echo "the variable needs to be filled"", or "if [ ! -z $VARIABLE ] ; then #everything is fine, proceed with the rest of the script".

1
  • 4
    [[ is not spawning two processes, it is a shell builtin (and [ is a Bash builtin too). [[ is different from [ [, which treats the second [ as a string Commented May 1, 2014 at 8:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.