2

I have a very small piece of code. And i am not sure where i am making it wrong. This is a simple IF condition, which should work.

#!/bin/bash

flag1=$1
flag2=$2

if [ "$flag1"="C" ] && [ "$flag2"="C" ]
then
echo "Proceed"

else
echo "Fail"

fi

I am running it using :- sh testif.sh C A and sh testif.sh C C

And i am getting same result in both. Proceed

I am new to Unix Scripting. Please tell me what blunder i am doing.

Sorry, for asking such a basic question.

4
  • 2
    You need spaces around the = signs. Commented Mar 13, 2015 at 13:04
  • You are aware that sh testif.sh will override the shebang, forcing this to be interpreted as sh instead of bash? Commented Mar 13, 2015 at 13:05
  • No, what is that ? Can you give some info ? Commented Mar 13, 2015 at 13:07
  • 1
    The line #!/bin/bash defines the default interpreter for the script in question -- the interpreter used if no interpreter is called explicitly (e.g. when you'd be calling ./testif.sh directly). When you're calling sh testif.sh, you are specifying sh to interpret the script. Now, most systems make /usr/bin/sh a link to /bin/bash -- but if invoked this way, bash will run in compatibility mode, mimicking original sh behaviour. Stuff like this can result in surprising errors -- for example, redirecting script output via exec > >(tee logfile.txt) will not work in sh mode. Commented Mar 13, 2015 at 13:12

2 Answers 2

4

You want space in between your bash tokens:

if [ "$flag1" = "C" ] && [ "$flag2" = "C" ]
Sign up to request clarification or add additional context in comments.

10 Comments

= is just fine, but you're right about the spaces.
@msfoster thanks, didn't realise the = operator is equivalent to == (just read from man bash). Edited answer accordingly.
@TusharKesarwani The first thing bash does is to break your input line into tokens roughly seperated by white space, then it looks at those token to parse the line. So you end up giveng bash the single token "$flag1"="C" which doesn't compute as a logical expression.
= and == are equivalent in bash, but == is a syntax error is some shells.
= and == are only equivalent in the [[ builtin, for [ the = operator is strictly string equality. Compare: [[ "bar" = *a* ]] && echo y outputs "y" but [ "bar" = *a* ] && echo y outputs bash: [: too many arguments (depending on the contents of your current directory)
|
1

Paul Evans's answer has the proper solution: you need (at least) a space character around operators such as = (and its equivalent in bash, ==).

As for why you needed that space:

Bash allows string concatenation simply by placing tokens next to each other without whitespace in between. Whether the tokens are quoted or not, and what quotes are used is irrelevant; e.g.:

'ab'cd"ef"  # -> Bash sees: abcdef

In the case at hand:

"$flag1"="C" # Bash eventually sees: <value-of-$flag1>=C

In other words: "$flag1"="C" evaluates to a single, nonempty string literal, and applying [ ... ] to such a string always evaluates to true.

Generally, see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128 in the POSIX shell spec. for information on how [ and its alias test treat differing numbers of arguments (thanks, @glennjackman).

For Bash to recognize the intended syntactic elements of "$flag1"="C" as such, you must therefore separate the elements with at least one space each.: "$flag1" = "C"


If you want your solution to be more bash-like, however, consider use of [[ ... ]] rather than POSIX syntax [ ... ]:

if [[ $flag1 == "C" && $flag2 == "C" ]] # ...

Benefits:

  • Allows you to use && inside a single [[ ... ]] construct.
  • Obviates the need to double-quote your variable references (though double-quoting never hurts and is actually important on the right side of = / == to distinguish string literals from patterns).
  • Performs slightly better.

Compatibility note: While [[ ... ]] works in bash and also zsh and ksh (though the behavior differs subtly), it is NOT POSIX-compliant. In situations where that is a concern, stick with [ ... ].

2 Comments

For your answer to be even better, you should talk about what [ (and test) does when given different numbers of arguments. (posix manual for test)
@glennjackman: Thanks for the tip, I've updated my answer accordingly.

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.