1

Here's an installer I'm writing with all the irrelevant bits removed:

#!/bin/bash

echo "In the prompt below, type 'install' or 'remove' (without the quotes)"
echo "If you type neither, this script will terminate."
read -p "Action to perform: " OPERATION

if [ "$OPERATION" == "install" ]
then
  echo "Installing..."
  echo "Install successful!"
elif [ "$OPERATION" == "remove" ]
then
  echo "Removing..."
  echo "Remove successful!"
else
  echo "Aborting with no actions"
fi

This script works exactly as you'd expect. When I type install, the install section executes, when I type remove the remove section executes and finally when I type random characters, it aborts.

But the same script with the #!/bin/bash replaced with either #!/bin/sh or left empty (my regular shell is ZSH), it errors out:

In the prompt below, type 'install' or 'remove' (without the quotes)
If you type neither, this script will terminate.
Action to perform: sdfsdfdsf
./test.sh: 7: [: sdfsdfdsf: unexpected operator
./test.sh: 11: [: sdfsdfdsf: unexpected operator
Aborting with no actions

For some context, I'm on Ubuntu Studio 18.04 with zsh --version printing zsh 5.4.2 (x86_64-ubuntu-linux-gnu).

Can someone help me understand why this is happening?

wingedrhino
  • 162
  • 1
  • 2
  • 8
  • On my laptop within zsh (5.3.1), read doesn't work as expected (read: -p: no coprocess). The if statement does work but only with asingle `=`, not with `==`. Maybe if you use `test` instead? (`if test "inst" != "install"; then echo "yes"; fi`). Your script should work within `sh`, however. – Bayou Jul 30 '19 at 12:46
  • @wingedrhino : If you don't have a #! line and invoke the script just by name, not via `zsh NAME`, zsh too will use /bin/sh, so this is not really a zsh issue. – user1934428 Jul 31 '19 at 08:03

2 Answers2

3

On ubuntu 18.04, /bin/sh is symlink to /bin/dash whose [ ... ] does not support ==. You can use [ = ] which also works for zsh.

[STEP 101] # grep 18.04 /etc/os-release
VERSION="18.04.2 LTS (Bionic Beaver)"
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
[STEP 102] # ls -l /bin/sh
lrwxrwxrwx 1 root root 4 2019-02-14 09:49 /bin/sh -> dash
[STEP 103] # /bin/sh
# [ a == b ]
/bin/sh: 1: [: a: unexpected operator
# test a == b
/bin/sh: 2: test: a: unexpected operator
# [ a = b ]
# test a = b
# exit
[STEP 104] #

Note that POSIX only mentions "=" and according to dash manual, "Only features designated by POSIX, plus a few Berkeley extensions, are being incorporated into this shell."

pynexj
  • 19,215
  • 5
  • 38
  • 56
  • 2
    In other words, `==` as a conditional operator is a Bash extension, so it's not surprising that it doesn't work in other shells. The standard string-equality comparison operator is `=`. – John Bollinger Jul 30 '19 at 13:02
  • Aah thanks! It works now. I rarely remember my shell scripting syntax so end up googling everything. I guess a lot of websites with references automatically assume you use bash! – wingedrhino Jul 30 '19 at 15:10
2

Fist you should update your shebang to use sh instead of bash and then you will have to use a slightly different syntax. You can use shellcheck for detailed errors.

There are a tone of articles describing the difference like: https://stackoverflow.com/a/5725402/3872881

#!/bin/sh

echo "In the prompt below, type 'install' or 'remove' (without the quotes)"
echo "If you type neither, this script will terminate."
echo -n "Action to perform: "
read -r OPERATION

if [ "$OPERATION" = "install" ]
then
  echo "Installing..."
  echo "Install successful!"
elif [ "$OPERATION" = "remove" ]
then
  echo "Removing..."
  echo "Remove successful!"
else
  echo "Aborting with no actions"
fi
kerhac
  • 176
  • 2
  • 5