700

I have this script called test.sh:

#!/bin/bash
STR = "Hello World"
echo $STR

when I run sh test.sh I get this:

test.sh: line 2: STR: command not found

What am I doing wrong? I look at extremely basic/beginners bash scripting tutorials online and this is how they say to declare variables... So I'm not sure what I'm doing wrong.

I'm on Ubuntu Server 9.10. And yes, bash is located at /bin/bash.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Jake Wilson
  • 88,616
  • 93
  • 252
  • 370
  • 112
    I'm glad you did ask the question, you're not the only bash noob out there! – miller the gorilla Aug 26 '15 at 10:40
  • 10
    Thanks for asking that question. This is not a question to be embarrassed about. I am working late night in office & there is no Bash expert around me to answer this. – Adway Lele Jan 19 '16 at 16:49
  • 4
    These days (almost seven years later!) there's a FOSS linter/analyzer called [shellcheck](http://www.shellcheck.net) that will autodetect this and other common syntax issues. It can be used online or installed offline and integrated in your editor. – that other guy Nov 08 '16 at 17:52
  • See also https://stackoverflow.com/questions/26971987/assignment-of-variables-with-space-after-the-sign – tripleee Oct 02 '17 at 13:36
  • I'd recommend you to use: `#!/usr/bin/env bash` instead of putting directly `#!/bin/bash` unless you're absolutely sure your `bash` is in `/bin` because of this answer: https://stackoverflow.com/a/21613044/3589567 – Alejandro Blasco Feb 21 '18 at 10:58

5 Answers5

1222

You cannot have spaces around the = sign.

When you write:

STR = "foo"

bash tries to run a command named STR with 2 arguments (the strings = and foo)

When you write:

STR =foo

bash tries to run a command named STR with 1 argument (the string =foo)

When you write:

STR= foo

bash tries to run the command foo with STR set to the empty string in its environment.

I'm not sure if this helps to clarify or if it is mere obfuscation, but note that:

  1. the first command is exactly equivalent to: STR "=" "foo",
  2. the second is the same as STR "=foo",
  3. and the last is equivalent to STR="" foo.

The relevant section of the sh language spec, section 2.9.1 states:

A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

In that context, a word is the command that bash is going to run. Any string containing = (in any position other than at the beginning of the string) which is not a redirection and in which the portion of the string before the = is a valid variable name is a variable assignment, while any string that is not a redirection or a variable assignment is a command. In STR = "foo", STR is not a variable assignment.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • 10
    If you have a variable with a name that contaings "-", the same error happens. In that case, the solution is to remove the "-" – chomp Jun 17 '16 at 02:27
  • 3
    chomp@ In rule 7b of section 2.10.10 of http://pubs.opengroup.org/onlinepubs/9699919799/ "If all the characters preceding '=' form a valid name (see XBD Name), the token ASSIGNMENT_WORD shall be returned." Following the link to section 3.231 of http://pubs.opengroup.org/onlinepubs/9699919799/, we find "In the shell command language, a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.". So the word `FOO-BAR=qux` is not a variable assignment since `FOO-BAR` is not a valid name. – William Pursell Jun 17 '16 at 13:30
  • 2
    I am offering a bounty to reward this clear explanation to an always common issue for beginners (well, and also to be able to find it faster whenever I want to link it :D). Thanks for making things this easy! – fedorqui Aug 16 '16 at 11:54
  • 1
    @fedorqui Thanks! I'm not entirely convinced that this is a clear explanation, and I often wonder if it could be made simpler. – William Pursell Aug 16 '16 at 21:29
  • I thought that "str= fo" is the cmd "str=" with arg "fo" but I was terribly wrong;) – Timo Nov 09 '20 at 15:56
  • My code `for i in ${ip_ar[@]} ;do;st=ste;st+=$j;$st=$i;echo $st;st='';((j++));done` also gets command not found. Any idea why? – Timo Nov 09 '20 at 16:00
  • If I have this array ip_ar=(3 2 3 2), I want to have ste=3, ste2=2, ste3=.. So a variable variable name. – Timo Nov 09 '20 at 16:15
  • 2
    @Timo `$st=$i` is not a variable assignment. It expands to a string, and that string is executed as a command. It seems like you are trying to do `eval $st=$i`. Don't do that. – William Pursell Nov 09 '20 at 17:05
  • @WilliamPursell thanks, there is associative array which is good to go. – Timo Nov 09 '20 at 20:23
201

Drop the spaces around the = sign:

#!/bin/bash 
STR="Hello World" 
echo $STR 
Joey
  • 344,408
  • 85
  • 689
  • 683
  • 11
    This is funny, though, as `set foo = bar` is a common mistake in Windows batch files as well—and there the batch language is ridiculed for it ;-) – Joey Feb 15 '10 at 18:36
  • Thanks @joey. I was stuck in writing a shell script where i was initializing variables with spaces after "=". You saved my day – Lalit Rao Oct 02 '15 at 13:10
  • Why bash doesn't accept numbers in the left field? like 3="Hello World", it complains about command not found – Freedo Jan 19 '18 at 16:51
10

In the interactive mode everything looks fine:

$ str="Hello World"
$ echo $str
Hello World

Obviously(!) as Johannes said, no space around =. In case there is any space around = then in the interactive mode it gives errors as

No command 'str' found

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Arkapravo
  • 4,084
  • 9
  • 37
  • 46
9

I know this has been answered with a very high-quality answer. But, in short, you cant have spaces.

#!/bin/bash
STR = "Hello World"
echo $STR

Didn't work because of the spaces around the equal sign. If you were to run...

#!/bin/bash
STR="Hello World"
echo $STR

It would work

Derek Haber
  • 137
  • 1
  • 3
  • 12
5

When you define any variable then you do not have to put in any extra spaces.

E.g.

name = "Stack Overflow"  
// it is not valid, you will get an error saying- "Command not found"

So remove spaces:

name="Stack Overflow" 

and it will work fine.

Knowledge Cube
  • 990
  • 12
  • 35
Ravi Solanki
  • 189
  • 3
  • 8