The first time I saw the error “Bash Unary Operator Expected” in the Linux terminal I thought: “And now? What do I do?” 😀
We will understand this error together and we will find a solution for it.
The Bash Unary Operator Expected error occurs when Bash identifies a line in your script that contains a binary operator that is not applied to two arguments. When this happens Bash assumes that you want to use a unary operator instead and raises the Unary Operator Expected error.
What Causes the Bash Unary Operator Expected Error?
The best way to understand an error is to write code where the error occurs and then go through any changes required to fix the error.
So, let’s follow this principle!
I will start with a simple Bash script called unary.sh
:
#!/bin/bash
DAY="monday"
if [ $DAY == "monday" ]; then
echo "Today is monday"
fi
When I run the script I get the following output:
[myuser@localhost]$ ./unary.sh
Today is monday
Now, let’s update line 3 of our script from:
DAY="monday"
to:
DAY=
After this change the variable DAY is empty.
Let’s execute the script again:
[myuser@localhost]$ ./unary.sh
./unary.sh: line 5: [: ==: unary operator expected
This time we see the error “unary operator expected”. Why?
Sometimes Bash errors don’t make much sense, or at least it looks like they don’t.
Why is Bash expecting a unary operator? And what is a unary operator?
Bash Unary and Binary Operators
What are unary and binary operators?
Bash operators are used in expressions that verify conditions as part of the logic of a script. Unary operators apply to one argument and are often used to verify the status of a file (e.g. does a specific file exist?). Binary operators apply to two arguments and are used, for example, as part of string or arithmetic comparisons (e.g. is a bigger than b?).
Now the error we are seeing makes a bit more sense.
./unary.sh: line 5: [: ==: unary operator expected
On line 5 of our script Bash expects a unary operator but the one we are using ( == ) is a binary operator.
Here is what happens when Bash reaches line 5 of the script:
if [ $DAY == "monday" ]; then
It replaces $DAY with its value, that in the first example is “monday”, so the line becomes:
if [ "monday" == "monday" ]; then
This expression is true and the echo command inside the if statement gets executed.
The operator == is a binary operator because it compares two values (arguments), the one on the left side of the operator with the one on the right side.
But, what happens when the value of the variable DAY is empty?
Line 5 of our script becomes:
if [ == "monday" ]; then
As you can see the left side of the comparison expression disappears and that’s why Bash prints the error “unary operator expected”.
Because the expression doesn’t contain two values anymore, but only one, “monday”.
How to Fix the Bash Unary Operator Expected Error
Now that we have a better understanding of the error, we also want to understand how to fix it.
How can we ensure our original expression keeps both arguments even when the variable DAY is empty?
The solution is to surround the variable $DAY in the comparison expression with double quotes.
The script becomes:
#!/bin/bash
DAY=
if [ "$DAY" == "monday" ]; then
echo "Today is monday"
fi
Notice how $DAY has become “$DAY”…
This time, when the variable DAY is empty and Bash reaches line 5 of the code, the if statement becomes:
if [ "" == "monday" ]; then
In this way, the comparison expression is still valid. In this case, the value of the expression is false and the script doesn’t print any output (and doesn’t error in the way we have seen before):
[myuser@localhost]$ ./unary.sh
[myuser@localhost]$
Bash Unary Operator Expected with While Loop
Let’s look at another script in which the same error occurs.
This time we will use a while loop in our script…
#!/bin/bash
while [ $INDEX -lt 5 ]
do
echo $INDEX
INDEX=$((INDEX+1))
done
I have created a simple script that uses a while loop to print the value of the variable INDEX and increase its value until it reaches 5.
When I run the script the error shows up again:
[myuser@localhost]$ ./unary_while.sh
./unary_while.sh: line 3: [: -lt: unary operator expected
Why?
One way to troubleshoot errors in a Bash script is by running the script using the following command:
bash -x <script_name>
Let’s give it a try:
[myuser@localhost]$ bash -x unary_while.sh
+ '[' -lt 5 ']'
unary_while.sh: line 3: [: -lt: unary operator expected
As you can see this allows us to see the way each line is interpreted by the Bash interpreter.
The problem is in the following line:
+ '[' -lt 5 ']'
The -lt comparison operator is a binary operator used to compare two numbers, but in this case, we can see only the number on the right side of the operator (the number 5).
What happened to the number on its left side?
It’s missing because we haven’t defined the variable INDEX before the while loop, let’s do it now:
#!/bin/bash
INDEX=0
while [ $INDEX -lt 5 ]
do
echo $INDEX
INDEX=$((INDEX+1))
done
This time when we run the script we get the expected result:
[myuser@localhost]$ ./unary_while.sh
0
1
2
3
4
And here is the way the bash -x output looks like this time:
[myuser@localhost]$ bash -x unary_while.sh
+ INDEX=0
+ '[' 0 -lt 5 ']'
+ echo 0
0
+ INDEX=1
+ '[' 1 -lt 5 ']'
+ echo 1
1
+ INDEX=2
+ '[' 2 -lt 5 ']'
+ echo 2
2
+ INDEX=3
+ '[' 3 -lt 5 ']'
+ echo 3
3
+ INDEX=4
+ '[' 4 -lt 5 ']'
+ echo 4
4
+ INDEX=5
+ '[' 5 -lt 5 ']'
Can you see how the value of the INDEX variable inside the test expression of the while loop increases at every iteration?
The script stops when INDEX reaches the value 5 because at that point the test expression of the while loop becomes false.
Unary Operator Expected when Checking For Empty String
One way to check if a string is empty in Bash is using the following if statement:
#!/bin/bash
MYSTRING=
if [ $MYSTRING == '' ]; then
echo "The string MYSTRING is empty"
fi
For the reasons explained in the previous sections the if statement will cause the “unary operator expected” error considering that the variable MYSTRING is empty.
As we have learned, one workaround would be surrounding $MYSTRING in the if statement with double quotes:
#!/bin/bash
MYSTRING=
if [ "$MYSTRING" == '' ]; then
echo "The string MYSTRING is empty"
fi
The script works well this time:
[myuser@localhost]$ ./unary_string.sh
The string MYSTRING is empty
To achieve the same purpose we can replace the binary operator == with the unary operator -z, that is used to verify if a string is empty.
If we use the -z test operator, the script becomes cleaner:
#!/bin/bash
MYSTRING=
if [ -z $MYSTRING ]; then
echo "The string MYSTRING is empty"
fi
You can run it and ensure you receive the output “The string MYSTRING is empty”.
Test Expression with Double Square Brackets
Another way to solve the error we are learning about in this article is by using test expressions with double square brackets ( [[ … ]] ) instead of single square brackets ( [ … ] ).
Let’s see how it works for the script that wasn’t working before (I have replaced [] with [[ ]]):
#!/bin/bash
MYSTRING=
if [[ $MYSTRING == '' ]]; then
echo "The string MYSTRING is empty"
fi
The script works fine:
[myuser@localhost]$ ./unary_string.sh
The string MYSTRING is empty
Why?
We can see why using the bash -x command:
[myuser@localhost]$ bash -x unary_string.sh
+ MYSTRING=
+ [[ '' == '' ]]
+ echo 'The string MYSTRING is empty'
The string MYSTRING is empty
As you can see, this time even if the variable MYSTRING is empty the comparison in the if statement contains empty strings for both arguments:
+ [[ '' == '' ]]
For this reason, we don’t see the unary operator expected error.
In a future article, I will explain the difference between single and double brackets in Bash with some examples.
Conclusion
Now you know what to do if you see the “unary operator expected” error and you know which parts of your scripts are likely to cause it.
In summary, the first place to look for is a Bash binary operator that compares the value of a variable with either a string or a number.
Once you find it look at what could make that variable empty and if you are surrounding that variable with double quotes.
And you? Where are you seeing this error in your scripts?
Let me know in the comments below 🙂
Related FREE Course: Decipher Bash Scripting
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design. He is a professional certified by the Linux Professional Institute.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for robotics with Raspberry Pi.