53

So I want to set some paths differently depending on the host, but unfortunately it's not working. Here is my script:

if [$HOSTNAME == "foo"]; then
    echo "success"
else
    echo "failure"
fi

This is what happens:

-bash: [foo: command not found
failure

I know for certain that $HOSTNAME is foo, so I'm not sure what the problem is. I am pretty new to bash though. Any help would be appreciated! Thanks!

4
  • 2
    Hint: the shell is whitespace sensitive. [x is different from [ x. Commented Apr 12, 2013 at 14:01
  • 2
    Hint: The test operator for string equality is =, not ==, even though the latter is accepted by buggy shells in a misguided attempt to ease programmers with less error messages. Commented Apr 12, 2013 at 14:02
  • @Jens can you elaborate on the attempt being misguided, it seems that == is a fairly standard equality operator syntax? I'm a software engineer now really using shell a lot these days and I'm just curious. Commented Nov 17, 2022 at 15:17
  • @nulltron The Standard is the Opengroup's UNIX specification and in that grammar only = is the comparison operator for test. Many years ago some shells started to make == synonymous. This made scripts using == suddenly non-portable and ill-behaved on conformant shells (of which there were many, and some still are around). Commented Nov 17, 2022 at 15:28

4 Answers 4

83

The POSIX and portable way to compare strings in the shell is

if [ "$HOSTNAME" = foo ]; then
    printf '%s\n' "on the right host"
else
    printf '%s\n' "uh-oh, not on foo"
fi

A case statement may be more flexible, though:

case $HOSTNAME in
  (foo) echo "Woohoo, we're on foo!";;
  (bar) echo "Oops, bar? Are you kidding?";;
  (*)   echo "How did I get in the middle of nowhere?";;
esac
Sign up to request clarification or add additional context in comments.

3 Comments

One, and only one. That's POSIX. Anything else is a bogus shell, accepting more than it should, promoting the == noncompliant script disease.
What is the diff between hostname and HOSTNAME? For comparison I need HOSTNAME. On wsl, hostname returns wsl and HOSTNAME the windows host.
@Jens nvm found what I was looking for.
4

You're missing a space after the opening bracket. It's also good "not to parse" the variable content using double quotes:

if [ "$HOSTNAME" = "foo" ]; then 
    ...

5 Comments

Double == is a bug. The equality operator is =. Some shells only accept it because of widespread ignorance :-)
You're right that it's not 100% POSIX correct, but I always tend to use == if it works.
You should rethink the "if it works" attitude. It won't work on many a popular shell, while = will work everwhere on any Unix since the epoch. One day you will find yourself on such a system. Ever heard of Solaris? And = is even less to type than ==.
There are many utilities that are kind of platform specific. I do care if there's a possibility that my script won't work. When I write a simple script for myself, who cares.
Attention to detail is the hallmark of professional programming. Why would anyone be less caring for their own scripting? I am caring, and I wish more people were, because it gets you in a habit of writing bullet-proof code from the start.
2
#!/bin/bash

if [[ $(hostname) == "home" ]] || [[ $(hostname) == "home2" ]]; then
    echo "True"
fi

Comments

0

Bash solution:

if [[ $HOSTNAME == 'foo' ]]; then
  echo 'yep this is foo'
else
  echo 'not foo'
fi

In regard to the response from @alper :

You can combine your logical OR (||) like this:

if [[ $(hostname) == "home" || $(hostname) == "home2" ]]; then
  echo "True"
fi

It's fine to do it the way you did, but I thought you might want to know you can save some keystrokes. One other critique is that using a subshell $() to execute the hostname command is slower than comparing against $HOSTNAME. There are valid reasons to do this in some environments, but the builtin environment variable $HOSTNAME should suffice for most simple use cases.

In response to @Jens: Bash supports the POSIX-compliant string-equality comparison operator (=), but has its own string-equality comparison operator (==) to differentiate it from the POSIX-compliant operator. This mirrors how bash's built-in test construct ([[ ]]) is doubled to differentiate it from the POSIX-compliant test contract ([ ]).

Calling bash a 'buggy shell' because it 'accepts' its own string-equality construct is a complete misrepresentation.

Saying that '==' is accepted by 'buggy shells in an attempt to ease programmers with less error messages' is totally false, not to mention bad grammar. You meant 'fewer' error messages.

Saying that '== is a bug' and 'some shells only accept it because of widespread ignorance' is completely wrong.

Solaris is being replaced with Linux more and more with each passing year in corporate environments. The majority of *nix servers run some flavor of Linux. So POSIX compliance in all shell scripts is no longer a hard requirement, and is increasingly irrelevant for a lot of environments.

Bash won the shell wars, because Linux won the *nix wars.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.