63

I'm not sure how to do an if with multiple tests in shell. I'm having trouble writing this script:

echo "You have provided the following arguments $arg1 $arg2 $arg3"
if [ "$arg1" = "$arg2" && "$arg1" != "$arg3" ]
then
    echo "Two of the provided args are equal."
    exit 3
elif [ $arg1 = $arg2 && $arg1 = $arg3 ]
then
    echo "All of the specified args are equal"
    exit 0
else
    echo "All of the specified args are different"
    exit 4
fi

The problem is I get this error every time:

./compare.sh: [: missing `]' command not found

Falko
  • 17,076
  • 13
  • 60
  • 105
Zenet
  • 6,961
  • 13
  • 38
  • 45
  • 8
    Quite a few commentators have suggested you use [[ rather than [ but that makes your script bash-specific. You'll have fewer maintenance and portability issues if you can stick to plain old Bourne shell (sh) syntax. – Adrian Pronk Mar 01 '10 at 22:01

6 Answers6

47

Josh Lee's answer works, but you can use the "&&" operator for better readability like this:

echo "You have provided the following arguments $arg1 $arg2 $arg3"
if [ "$arg1" = "$arg2" ] && [ "$arg1" != "$arg3" ]
then 
    echo "Two of the provided args are equal."
    exit 3
elif [ $arg1 = $arg2 ] && [ $arg1 = $arg3 ]
then
    echo "All of the specified args are equal"
    exit 0
else
    echo "All of the specified args are different"
    exit 4 
fi
Falko
  • 17,076
  • 13
  • 60
  • 105
Splitlocked
  • 711
  • 6
  • 10
40

sh is interpreting the && as a shell operator. Change it to -a, that’s [’s conjunction operator:

[ "$arg1" = "$arg2" -a "$arg1" != "$arg3" ]

Also, you should always quote the variables, because [ gets confused when you leave off arguments.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
8

I have a sample from your code. Try this:

echo "*Select Option:*"
echo "1 - script1"
echo "2 - script2"
echo "3 - script3 "
read option
echo "You have selected" $option"."
if [ $option="1" ]
then
    echo "1"
elif [ $option="2" ]
then
    echo "2"
    exit 0
elif [ $option="3" ]
then
    echo "3"
    exit 0
else
    echo "Please try again from given options only."
fi

This should work. :)

Falko
  • 17,076
  • 13
  • 60
  • 105
  • Gawd this looks quirky to me. Why no `then` after `else`? It may actually not be quirky, but that's how it looks, compared to C. – Rolf Nov 10 '17 at 22:01
  • space is required after $option and before = to run it fine, else every time 1 – PiyusG Feb 09 '18 at 07:46
8

Use double brackets...

if [[ expression ]]

Henryk Konsek
  • 9,016
  • 5
  • 32
  • 41
  • 2
    To note, this is a solution because the `[[` construct is built into the shell while `[` is another name for the `test` command and hence is subject to its syntax -- see `man test` – glenn jackman Mar 01 '10 at 23:54
  • 5
    Technically, `[` is a shell builtin, but `[[` is a shell keyword. That’s the difference. – Josh Lee Mar 02 '10 at 06:45
  • 1
    So see the results of the bash commands `type [`, `type [[`, `help [` and `help [[`. – Apostle Feb 10 '14 at 14:31
  • @JoshLee no, there is a file called `/usr/bin/[` – LtWorf Mar 03 '17 at 10:14
5

Change [ to [[, and ] to ]].

NAND
  • 663
  • 8
  • 22
Ethan Post
  • 3,020
  • 3
  • 27
  • 27
1

This is working for me,

 # cat checking.sh
 #!/bin/bash
 echo "You have provided the following arguments $arg1 $arg2 $arg3"
 if [ "$arg1" = "$arg2" ] && [ "$arg1" != "$arg3" ]
 then
     echo "Two of the provided args are equal."
     exit 3
 elif [ $arg1 == $arg2 ] && [ $arg1 = $arg3 ]
 then
     echo "All of the specified args are equal"
     exit 0
 else
     echo "All of the specified args are different"
     exit 4
 fi

 # ./checking.sh
 You have provided the following arguments
 All of the specified args are equal

You can add set -x in script to troubleshoot the errors.

NAND
  • 663
  • 8
  • 22
Ranjithkumar T
  • 1,886
  • 16
  • 21