431

I can't seem to work out what the issue with the following if statement is in regards to the elif and then. Keep in mind the printf is still under development I just haven't been able to test it yet in the statement so is more than likely wrong.

The error I'm getting is:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

And the statement is like so.

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
StuStirling
  • 15,601
  • 23
  • 93
  • 150
  • 10
    I wonder why we **need** the `then` statement in `if` and `elif` but not in `else`, and also in general. –  Jul 16 '17 at 04:50
  • 2
    @w17t, because we need to separate condition from sequence. – Sasha Jan 02 '19 at 20:40
  • 5
    @codeforester I don't see much logic on marking a 500K views question as a duplicate to one that has only 5K – fedorqui May 15 '19 at 09:41
  • Using some code auto-formatting tools might help you by automatically adding/removing spaces around the brackets. You can search for plugins for your editor. – Nj Subedi Jun 07 '19 at 17:09
  • for me , i never expected a semicolon at the end of 'if' statement followed by 'then'.Your question itself was the solution for me. Thanks a lot !! – Shan Jun 15 '21 at 10:05

5 Answers5

530

There is a space missing between elif and [:

elif[ "$seconds" -gt 0 ]

should be

elif [ "$seconds" -gt 0 ]

All together, the syntax to follow is:

if [ conditions ]; then
   # Things
elif [ other_conditions ]; then
   # Other things
else
   # In case none of the above occurs
fi

As I see this question is getting a lot of views, it is important to indicate that the syntax to follow is:

if [ conditions ]
# ^ ^          ^

meaning that spaces are needed around the brackets. Otherwise, it won't work. This is because [ itself is a command.

The reason why you are not seeing something like elif[: command not found (or similar) is that after seeing if and then, the shell is looking for either elif, else, or fi. However it finds another then (after the mis-formatted elif[). Only after having parsed the statement it would be executed (and an error message like elif[: command not found would be output).

fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 37
    The reason the brackets need spaces is because they are just shortcuts for actual programs (at least the first bracket, the second one is just syntactic sugar as I understand it). To make sense of it, see the actual manpage for left bracket: `$ man [` – Michael Johansen May 16 '17 at 21:58
  • 4
    Is this post not supposed to be closed as typo? – zx8754 Nov 16 '18 at 14:58
  • 3
    @zx8754 could have been, but not it became a canonical way to fix this error, which looks quite useful (360K views and counting). – fedorqui Nov 16 '18 at 15:02
  • Still, closing the post doesn't make it any less valid. But of course it is up to you, I am not frequent in "bash/linux" tags. – zx8754 Nov 16 '18 at 15:05
  • 4
    Some of my colleagues don't understand the concept of a "space" or "coding style" so this might not be a typo. – juzzlin Mar 06 '19 at 14:08
  • @MichaelJohansen in my centos7 the input `$ man [` got output `bash: $: command not found...`, what is wrong? – Lei Yang Mar 25 '19 at 15:15
  • 3
    [ is a kind of alias for the test command. This is why the blank character is required. `if test "$seconds" -eq 0; then ... fi` is equivalent to `if [ "$seconds" -eq 0 ];then ... fi ]`. @LeiYang `man test`is what you actually looking for – Melicerte May 15 '19 at 09:33
342

You have some syntax issues with your script. Here is a fixed version:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi
James Ray
  • 424
  • 3
  • 15
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 92
    Oddly enough, this was the only complete and *simple* `bash` "if-then-else" construct I easily found on stackexchange...thanks. – Wildcard Jan 06 '16 at 00:11
  • 1
    indentation is optional. the interpreter can (and should) be `#!/bin/sh`. –  Jul 16 '17 at 04:44
  • 3
    @Chinggis6 Total nonsense, the interpreter **could** be `#!/bin/sh` but doesn't have to. – Camusensei Sep 13 '17 at 14:19
  • 5
    @Camusensei it's not a total nonsense as `sh` can be used instead for higher compatibility (not all *nix distros has [tag:bash] as the default shell (some have ksh or ash but most of them do depend on the standard `sh` to function). Moreover if bash's specific or advanced features is not being used in the script then 'sh' should be used as the interpreter (one more reason for it) as it can handle the script by itself. –  Sep 13 '17 at 14:38
  • 8
    @Chinggis6 True, bad choice of words on my side. – Camusensei Sep 14 '17 at 15:18
28

[ is a command (or a builtin in some shells). It must be separated by whitespace from the preceding statement:

elif [
choroba
  • 231,213
  • 25
  • 204
  • 289
9

I would recommend you having a look at the basics of conditioning in bash.

The symbol "[" is a command and must have a whitespace prior to it. If you don't give whitespace after your elif, the system interprets elif[ as a a particular command which is definitely not what you'd want at this time.

Usage:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

In short, edit your code segment to:

elif [ "$seconds" -gt 0 ]

You'd be fine with no compilation errors. Your final code segment should look like this:

#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi
Mr. Weirdo
  • 115
  • 1
  • 9
6

Missing space between elif and [ rest your program is correct. you need to correct it an check it out. here is fixed program:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

useful link related to this bash if else statement

John Walsh
  • 179
  • 2
  • 3