Bash | Why should you put shell variables always between quotation marks ? (+ real world example)
Paladuta Stefan
Posted on July 26, 2023
This memo will help you understand how using quotation marks around shell variables can help ensure that they are interpreted correctly and can help avoid unexpected behavior.
You should put shell variables inside quotation marks to ensure that they are interpreted correctly by the shell. When you use a variable in a shell command or script without quotation marks, the shell will expand the variable, which means it will replace the variable with its value. This can cause problems if the variable contains spaces, special characters, or other characters that the shell interprets in a special way.
By enclosing the variable in quotation marks, you tell the shell to treat the entire string as a single argument, even if it contains spaces or other special characters. This can prevent errors and unexpected behavior in your shell commands and scripts.
For example, consider the following code:
MYVAR="Hello World"
echo $MYVAR
Without quotation marks, Bash will split the value of MYVAR into two separate words, "Hello" and "World", and treat them as separate arguments to echo, resulting in the output:
Hello World
However, if you put the variable in double quotes, like this:
MYVAR="Hello World"
echo "$MYVAR"
The entire value of MYVAR is treated as a single argument to echo, resulting in the output:
Hello World
Similarly, if your variable contains special characters such as asterisks or question marks, Bash will interpret them as globbing patterns and try to expand them into filenames in the current directory. This can lead to unexpected behavior or errors. Using quotes can prevent this behavior and ensure that the variable is treated as a literal string.
Therefore, it is generally a good practice to always put your shell variables inside double quotes unless you have a specific reason not to.
Real world example of bad management of quotation in shell scripting.
Consider the following scenario:
EX_VARIABLE="24/22/2021"
SQL_MSG=`sqlplus -s <user>/<pwd>@<db> <<-EOF
whenever SQLERROR EXIT SQL.SQLCODE ROLLBACK;
whenever OSERROR EXIT SQL.SQLCODE ROLLBACK;
select to_date('${EX_VARIABLE}','dd/mm/yyyy') from dual;
EOF`
if [ $? -eq 0 ]; then
echo "OK";
else
echo ${SQL_MSG}
fi
The objective of this shell script is to check if the conversion from the string representation of a date (stored in the EX_VARIABLE variable) is working properly by evaluating whether it is a valid date.
# ./sh_example.sh
select to_date('24/22/2021','dd/mm/yyyy') from dual bin boot dev
docker-entrypoint-initdb.d etc home lib lib64 media mnt
opt proc root run sbin sh_example sh_example.sh srv sys tmp u01
usr var ERROR at line 1: ORA-01843: not a valid month
However, due to the lack of quotation marks around the SQL_MSG variable in the echo statement, the output includes extraneous information, such as the names of all the files in the current directory and if we check the content of the path where the shell is present:
we can see that the junk in fact represents all the files and logs from that specific folder !
- bin
- boot
- dev
- docker-entrypoint-initdb.d
- etc
- var
- etc.
Reason of the behaviour
If we revisit the shell code again:
EX_VARIABLE="24/22/2021"
SQL_MSG=`sqlplus -s <user>/<pwd>@<db> <<-EOF
whenever SQLERROR EXIT SQL.SQLCODE ROLLBACK;
whenever OSERROR EXIT SQL.SQLCODE ROLLBACK;
select to_date('${EX_VARIABLE}','dd/mm/yyyy') from dual;
EOF`
if [ $? -eq 0 ]; then
echo "OK";
else
echo "${SQL_MSG}" #This was the only line of code changed
fi
but this time we are going to rewrite the line “echo ${SQL_MSG}”, more specific the variabile ${SQL_MSG} with quotation marks and run the shell again:
root@9ea9fad92c38:/# ./sh_example.sh
select to_date('24/22/2021','dd/mm/yyyy') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
we can see that this time it worked but what happened ?
Because the quotation marks were missing my theory is that the echo command tried to do echo of each of the lines that we see in the output:
- echo select to_date(‘24/22/2021’,’dd/mm/yyyy’) from dual
- echo * <- and echo * actually is a command that returns you the list of all the files and folder from the current directoy so the junk that we saw in red is actually the result of this command
- echo ERROR at line 1:
If you liked the article please take a minute to offer me a clap 👏 or even buy me a coffee https://www.buymeacoffee.com/stefansplace (;
Posted on July 26, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.