227

I am trying to compare strings in bash. I already found an answer on how to do it on stackoverflow. In script I am trying, I am using the code submitted by Adam in the mentioned question:

#!/bin/bash
string='My string';

if [[ "$string" == *My* ]]
then
  echo "It's there!";
fi

needle='y s'
if [[ "$string" == *"$needle"* ]]; then
  echo "haystack '$string' contains needle '$needle'"
fi

I also tried approach from ubuntuforums that you can find in 2nd post

if [[ $var =~ regexp ]]; then
  #do something
fi

In both cases I receive error:

[[: not found

What am I doing wrong?

Community
  • 1
  • 1
user1581900
  • 3,680
  • 4
  • 18
  • 21

10 Answers10

256

[[ is a bash-builtin. Your /bin/bash doesn't seem to be an actual bash.

From a comment:

Add #!/bin/bash at the top of file

Abhay
  • 3,151
  • 1
  • 19
  • 29
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
219

How you are running your script? If you did with

$ sh myscript

you should try:

$ bash myscript

or, if the script is executable:

$ ./myscript

sh and bash are two different shells. While in the first case you are passing your script as an argument to the sh interpreter, in the second case you decide on the very first line which interpreter will be used.

Fermin Silva
  • 3,331
  • 2
  • 17
  • 21
Akos K
  • 7,071
  • 3
  • 33
  • 46
  • i got permission denied this way. with sudo ./myscript its command not found – user1581900 Sep 01 '12 at 19:37
  • 11
    do **chmod +x myscript**, then run again, you don't need sudo – Akos K Sep 01 '12 at 19:41
  • 2
    How you are invoking you script? – Akos K Sep 01 '12 at 19:48
  • like you said. normally i call it with '$sh myscipt.sh'. 2nd time after doing chmod +x myscript.sh i called it with ./myscript.sh – user1581900 Sep 01 '12 at 20:02
  • 5
    The error is expected when you run the script via `sh myscript.sh`, because `/bin/sh` emulates a Bourne shell where `[[` is not a builtin. However, running the script via `./script.sh` should not yield an error, because in that case the shebang should cause `/bin/bash` to be used. – Ansgar Wiechers Sep 01 '12 at 20:08
  • See also [Difference between `sh` and `bash`](/q//5725296) which elaborates on the differences. – tripleee Mar 05 '18 at 13:06
85

Is the first line in your script:

#!/bin/bash

or

#!/bin/sh

the sh shell produces this error messages, not bash

Kevin
  • 53,822
  • 15
  • 101
  • 132
Wiley
  • 1,156
  • 7
  • 4
28

As @Ansgar mentioned, [[ is a bashism, ie built into Bash and not available for other shells. If you want your script to be portable, use [. Comparisons will also need a different syntax: change == to =.

if [ $MYVAR = "myvalue" ]; then
    echo "true"
else
    echo "false"
fi
Etienne Gautier
  • 2,901
  • 4
  • 26
  • 35
Amedee Van Gasse
  • 7,280
  • 5
  • 55
  • 101
  • Checked a bit with Ubuntu 16.04 and (sh ->) dash 0.5.8-2.1ubuntu2 and found that [ works fine in combination with "-eq" and alikes. Similar information on comparison operators for this context can be found here: https://stackoverflow.com/questions/10849297/compare-a-string-using-sh-shell - I further cheked with (( )) evaluation operator as recommended in the next link but that seemed to fail for my minimal invasive changes /or/ it would need a much deeper level of code changes. http://www.softpanorama.org/Scripting/Shellorama/Control_structures/comparison_operators.shtml – Alexander Stohr Jan 27 '20 at 08:00
17

I had this problem when installing Heroku Toolbelt

This is how I solved the problem

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ago 15  2012 /bin/sh -> dash

As you can see, /bin/sh is a link to "dash" (not bash), and [[ is bash syntactic sugarness. So I just replaced the link to /bin/bash. Careful using rm like this in your system!

$ sudo rm /bin/sh
$ sudo ln -s /bin/bash /bin/sh
jperelli
  • 6,988
  • 5
  • 50
  • 85
  • 7
    Overriding the default `sh` for your distro is ill-advised IMHO. A shell which is run with `sh` should work with `dash`; if it doesn't, that's a bug in the script. If you need `bash` features, use `bash`, not `sh`. – tripleee Dec 15 '15 at 08:46
  • 4
    this sounds terrible tbh – MrVaykadji Mar 08 '16 at 03:10
  • 2
    I agree, it was just an ugly workaround. A similar but better workaround would be to use `update-alternatives` (in debian-based-linux) like this https://justinconover.wordpress.com/2012/05/14/ubuntu-changing-dash-to-bash/ but in the end, it would be the same. – jperelli Mar 08 '16 at 13:53
10

If you know you're on bash, and still get this error, make sure you write the if with spaces.

[[1==1]] # This outputs error

[[ 1==1 ]] # OK
Richard Miller
  • 576
  • 1
  • 7
  • 18
4

Specify bash instead of sh when running the script. I personally noticed they are different under ubuntu 12.10:

bash script.sh arg0 ... argn

Smeterlink
  • 716
  • 6
  • 20
3

Execute in your terminal:

sudo update-alternatives --install /bin/sh sh /bin/bash 100
Antonio Moreno
  • 881
  • 8
  • 9
0

Make the file executable and then execute without sh.

  1. make it executable by $ chmod +x filename
  2. then instead of sh filename use ./filename
0

I had the same error (on a Mac) – but due to the fact, that I entered a space before the "[" with the option key already down for typing the "[". So the space character was not the space character I wanted to type, but a "nonbreaking space". Not visible in the text editor – but caused a "[[ : command not found" error.

CreaTurE
  • 11
  • 1
  • This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). To get notified when this question gets new answers, you can [follow this question](https://meta.stackexchange.com/q/345661). Once you have enough [reputation](https://stackoverflow.com/help/whats-reputation), you can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question. - [From Review](/review/late-answers/34638384) – Yogendra Jul 07 '23 at 08:35