Ubuntu – If/Else in shell script throws errors in Ubuntu for Windows

bashcommand linescriptswindows 10windows-subsystem-for-linux

Here's an example simple shell script:

#!/usr/bin/env bash
if [ 1 == 1 ]; then
echo "Something"

When I run this

sh ./test.sh

I get:

./test.sh: 4: ./test.sh: Syntax error: "fi" unexpected (expecting "then")

It doesn't seem to recognize the 'then' I have in there. Any clue as to why? This is Ubuntu for Windows in case that part matters.

Running shell scripts in general is not a problem, it just seems to struggle with if/else.

Best Answer

There are two problems here. First, while you have a shebang line calling bash, you are executing the script as sh script.sh. The shebang line already specifies an interpreter for this script. So, just make the script executable:

chmod a+x ./test.sh

And then run it:


Alternatively, run it with bash explicitly:

bash ./test.sh

That will make it run with bash instead of sh which is a more limited shell and doesn't understand ==. Which brings us to the second problem and why this fails. Strangely enough, you want eq or =, not ==. The operator that tests numerical equality in POSIX shell scripts (sh is a POSIX-compliant shell) is -eq while the one that tests string equality is = and == isn't a thing.

So, if you want your script to be run by sh, change it to:

if [ 1 = 1 ]; then
    echo "Something"

Which checks that the string 1 is the same as the string 1, or to compare numerically, use:

if [ 1 -eq 1 ]; then
    echo "Something"

In addition, you have another problem. I can only reproduce the specific error you get in dash if I add a \r after the then. This is a classic problem when moving between Windows and Linux. While Linux uses \n as the line end character, Windows ends its lines with \r\n. This \r character is not visible to the user, but it is there and confuses the script. So, you can remove it with:

sed -i 's/\r//' ./test.sh

And in the future, use a proper text editor to write your scripts. Either one that works in the WSL system, or one that can at least be configured to not add \r to the ends of its lines.