String comparison in bash. [[: not found - bash

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?

[[ 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

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.

Is the first line in your script:
#!/bin/bash
or
#!/bin/sh
the sh shell produces this error messages, not bash

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

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

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

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

Execute in your terminal:
sudo update-alternatives --install /bin/sh sh /bin/bash 100

Make the file executable and then execute without sh.
make it executable by $ chmod +x filename
then instead of sh filename use ./filename

Related

nesting if in a for loop for aws cli commands [duplicate]

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?
[[ 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
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.
Is the first line in your script:
#!/bin/bash
or
#!/bin/sh
the sh shell produces this error messages, not bash
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
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
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
Specify bash instead of sh when running the script. I personally noticed they are different under ubuntu 12.10:
bash script.sh arg0 ... argn
Execute in your terminal:
sudo update-alternatives --install /bin/sh sh /bin/bash 100
Make the file executable and then execute without sh.
make it executable by $ chmod +x filename
then instead of sh filename use ./filename

Why can a script with a "#!/bin/sh" shebang use bash-only features?

When I run the following script :
#!/bin/sh
declare path="my.path"
if [[ "$path" =~ \. ]] ; then
echo "yes"
else
echo "no"
fi
I got yes printed.
But if I am not mistaken, declare and [[ ]] are not available in POSIX shell ; so how come this script does not throw any error ?
I run the script on git for Windows, could it explain this odd behavior ?
/bin/sh is a link to your actual shell. It does not mean that you are running pure POSIX. The Git for windows homepage makes very clear that you are running bash, as does your git-bash tag.
Even on Linux, /bin/sh can still be bash:
ls -la /bin/sh
lrwxrwxrwx. 1 root root 4 Mar 27 09:33 /bin/sh -> bash

How to check the current shell and change it to bash via script?

#!/bin/bash
if [ ! -f readexportfile ]; then
echo "readexportfile does not exist"
exit 0
fi
The above is part of my script. When the current shell is /bin/csh my script fails with the following error:
If: Expression Syntax
Then: Command not found
If I run bash and then run my script, it runs fine(as expected).
So the question is: If there is any way that myscript can change the current shell and then interpretate rest of the code.
PS: If i keep bash in my script, it changes the current shell and rest of the code in script doesn't get executed.
The other replies are correct, however, to answer your question, this should do the trick:
[[ $(basename $SHELL) = 'bash' ]] || exec /bin/bash
The exec builtin replaces the current shell with the given command (in this case, /bin/bash).
You can use SHEBANG(#!) to overcome your issue.
In your code you are already using she-bang but make sure it is first and foremost line.
$ cat test.sh
#!/bin/bash
if [ ! -f readexportfile ]; then
echo "readexportfile does not exist"
exit 0
else
echo "No File"
fi
$ ./test.sh
readexportfile does not exist
$ echo $SHELL
/bin/tcsh
In the above code even though I am using CSH that code executed as we mentioned shebang in the code. In case if there is no shebang then it will take the help of shell in which you are already logged in.
In you case you also check the location of bash interpreter using
$ which bash
or
$ cat /etc/shells |grep bash

Argument passing in a bash script

I've got following bash script to do something for each parameter of the script
#! /bin/sh
while (($#)); do
echo $1
shift
done
But somehow, if I start it with the command sudo ./test.sh foo1 foo2 it wont work. And the real strange thing is, that if I enter sudo bash test.sh foo1 foo2 it works. Does anybody know what causes this strange behaviour?
You have specified /bin/sh as your interpreter, which may not be bash. Even if it is bash, bash runs in POSIX mode when called as /bin/sh.
The (( )) command is a bash-specific feature. The following will work in any POSIX compliant shell:
while [ $# -gt 0 ]; do
echo $1
shift
done
Have you tried #!/bin/bash rather than sh?
Here's a link explaining the difference:
http://www.linuxquestions.org/questions/programming-9/difference-between-bin-bash-and-bin-sh-693231/
This will work in either sh or bash:
for arg
do
echo "$arg"
done
and it does the same thing as your script is intended to do without destroying the argument list.

Shell script works in bash but not in ksh

I need to write a script to test if the command blablabla exists in the classpath. So I wrote the following code:
if ! hash blablabla >/dev/null 2>&1; then
echo not found
fi
This works fine when the script is executed in the bash. But if I try it in KSH, then it doesn't work:
#! /usr/bin/ksh
if ! hash blablabla >/dev/null 2>&1; then
echo not found
fi
I expect the echo not found to be executed but instead I get nothing. What's the problem?
I believe command is portable (if that matters):
command -v -- some_command >/dev/null 2>&1 ||
printf '%s\n' "not found"
In bash hash is a builtin command. In ksh it's an alias; aliases aren't active in shell scripts.
alias hash='alias -t --'
Try the which command, which is an external command and therefore shell-independent:
if ! which -s blablabla; then
echo not found >&2
fi
Tha hash command is a shell built-in command in bash, but not in ksh. You might want to use whence instead.
if ! whence blah; then print urgh; fi

Resources