The variable assignment in bash may seem straightforward at the first glance, but there exist a few counter-intuitive pitfalls. If you have ever felt like “why can’t I have whitespace in here?!” or “bash is insane!”, then this article is for you. Once you know the rules behind the syntax of variable assignment in bash, you will see that it actually makes a lot of sense.

How to assign variables in bash?

The variable assignment looks just like in any other programming language.

$ MY_VARIABLE=myvalue

Here the string value "myvalue" is assigned to the variable named MY_VARIABLE. If you want to get the value of a variable, you can use the $ operator. This is called a parameter expansion.

$ echo ${MY_VARIABLE}
myvalue
$ echo $MY_VARIABLE #simplified syntax
myvalue

Beware of whitespace surrounding =

So, this is how you assign variables:

$ A=B

Here the string value "B" will be assigned to variable named A. If you are new to bash (e.g. coming from C, Python or other programming language), then you may want to include some whitespace to make this assignment more readable.

$ A = B

It was one of the first mistakes that I used to make. What is going to happen here? Let’s see.

$ A = B
A: unknown command

This is not a syntax error. It doesn’t work, because it is not interpreted as variable assignment syntax. It is interpreted as a simple command, which is defined in bash the following way: >It’s a sequence of words separated by blanks. >The first word generally specifies a command to be executed, with the rest of the words being that command’s arguments.

Bash will attempt to execute a command A with = given as first argument and B as the second.

Let’s consider another example

$ A= B
B: unknown command

This is another trap that you can fall into just by making a typo. The error is again not a syntax error, but this time B is intepreted as a command. Why?

Turns out that bash will interpret A= as a variable assignment preceding the command name. Such assignments only affect the environment of the executed command. For example if you wanted to open a man for ls program, but you wanted to use a more pager you could execute the following command:

$ MANPAGER=more man ls

This has almost the same effect as:

$ export MANPAGES=more
$ man ls

With the exception that the former example would only affect the environment of a man process and the latter would affect the environment of current bash session.

So in this example:

$ A= B
B: unknown command

Bash would attempt to execute B command with variable A in its environment, which would be set to an empty value.

Strings should be quoted

In previous examples of assignments you could see that string values don’t have to be quoted. There are cases where quotes are neccessary. For example:

$ caption=hello my friend

From previous examples you can learn that here bash would attempt to execute my program with word friend given as a first argument and with caption variable set to "hello" value in its environment. You can enclose the string with quotes or escape whitespace characters with \ character:

$ caption="hello my friend"
$ caption=hello\ my\ friend

Variables don’t have to be quoted

Another interesting example concerns the feature called word splitting. In bash the world splitting occurs during parameter expansion when variable isn’t quoted:

$ hello="mkdir foo"
$ $hello #will call 'mkdir' with 'foo' as a first argument
$ "$hello" #will try call 'mkdir foo' program
mkdir foo: unknown command

So when performing the following assignment:

$ foo="a b"
$ bar=$foo

You may think that it would result in:

$ bar=a b

Which is calling b command with bar=a in its environment. This is not the case, however. Turns out that bash doesn’t perform word splitting when it comes to variable assignment. So this results in:

$ bar="a b"

Did you expect it? I didn’t.

Summary

There are few surprises when it comes to variable assignment, but once you know what is the reasoning behind they are not that surprising.