echo "$VARIABLE"
Should you ALWAYS wrap your variables in quotes??? Some would say, "Yes! Absolutely, always wrap your variables in quotes. Just to be safe!" Well, I say, "You do you, dawg".
Fortunately, I'm not just going to leave you hanging there. Let's explore the differences between wrapping our variables in quotes and see what the differences are. Then, we can determine for ourselves, when is the best time to use quotes around our variables. All the time, or some of the time? Decide for yourself!
$HOME and $PATH
echo $HOME
home/jimmy
echo "$HOME"
home/jimmy
Well, it doesn't seem like there's much of a difference here! Let's create a variable with some spaces in it and see what happens.
NAME="Jimmy McBride"
echo $NAME
Jimmy McBride
echo "$NAME"
Jimmy McBride
Now, we're getting somewhere! It seems like if we have more than 1 empty space in a variable and if those spaces are important we need wrap our variable in quotes!
Rule of thumb: If your variable contains more than 1 consecutive white space and that white space is important for any reason then you DEFINITELY want to wrap your variable in quotes.
Let's create a variable with a wildcard (*) and see what happens...
NAME="Jimmy McBride *"
echo $NAME
Jimmy McBride bin calc Desktop Documents Downloads Games indicator-bulletin Music Pictures Postman Public Templates Videos
Uh-oh! Looks like, instead of printing out "Jimmy McBride *" It printed out "Jimmy McBride" plus all of our files in our home folder. That's most likely not what we wanted.
NAME="Jimmy McBride *"
echo "$NAME"
Jimmy McBride *
Now that looks a whole lot better!
Rule of thumb: If you have a wildcard character (*) in your code and you want it to act as a regular character you DEFINITELY want to wrap your variable in quotes. However, if you intend for it to be and act as an actual wildcard, then you should NOT wrap your variable in quotes.
Let's play around a bit with putting variables in quotes...
NAME="Jimmy McBride"
echo $NAME $HOME
Jimmy McBride /home/jimmy
echo $NAME $HOME
Jimmy McBride /home/jimmy
echo "$NAME $HOME"
Jimmy McBride /home/jimmy
echo $NAME * $HOME
Jimmy McBride bin calc Desktop Documents Downloads Games indicator-bulletin Music Pictures Postman Public Templates Videos /home/jimmy
echo "$NAME" * "$HOME"
Jimmy McBride bin calc Desktop Documents Downloads Games indicator-bulletin Music Pictures Postman Public Templates Videos /home/jimmy
echo "$NAME * $HOME"
Jimmy McBride * /home/jimmy
Conclusion
If you variable doesn't contain consecutive white spaces that are important or if you have a wild card symbol that you don't want to behave as a wildcard, you definitely want to wrap you variable in quotes.
If you have a variable with a wildcard and you want it to behave as a wildcard, then you definitely want to wrap that puppy in quotes.
If the variable you are calling doesn't have important consecutive white spaces or contain a wildcard character then it doesn't seem to make a difference whether or not you use quotes or not. In that situation, especially when I know what the variables are, I would save my self a few keystrokes by not adding quotes. However, if you are ever uncertain when using a variable, wrapping it in quotes just to be safe might be a really good idea!
What are your thoughts? Did I miss anything? What's your opinion? Let me know in the comments! Thanks! π
Top comments (7)
There's one really big one you missed:
If you need the shell to treat each 'word' of your variable as separate arguments for a command, you need to not quote the variable when expanding it.
This also happens to explain the behavior surrounding whitespace:
This is also one of the big reasons that you almost always see variables quoted when doing expansion for conditionals, and almost never see them quoted for expansion as part of a
for
loop. The first case (conditionals) almost always wants the contents of the variable as a single argument, while the second almost always wants each item to be a separate argument.That's actually a super good point! I'm going to update this very soon. Thank you!
My opinion, you should always quote. And only exclude quotes in the "special" scenarios mentioned. Not the other way around. In my experience, if you are always asking the question "do I need to add quotes here", and only add them when you think yes, down the road you'll find out you should have, especially when someone not you on Windows or macos uses your script (they love spaces in filenames). Just get into the habit. It makes safer code. (I can't think of an easy example without
eval
offhand)Now you tried to be safe with the
eval
by adding the echo but now you have an arbitrary execution by accident. If you just got in in the habit of always using the quotes, then you would be better offGoing back to the case of
echo $NAME
, how can I say "I want to explicitly support wildcard/home dir expansion and still use quotes?"Now the code clearly show you mean to expand
NAME
, and you can use the array NAMES with quotes still.As a side note, on the subject of "to curly or not to curly", I say always curly
Instead of discovering you need to add
{}
, if you always add them, your script will just work.I'll end with one of my favorite bashisms.
A sane person would say of course my directory doesn't have spaces in it. A windows person would say of course my folder has spaces in it.
Update:
I should add, the exception that is the rule is
[[]]
. While you should always use quotes in[]
statements, you should probably never use them in[[]]
statements, as they are more advanced, and don't need the quotes. In face, the quotes are literal, and can give you the wrong answer.Wow, nice work man! Yeah, this definitely changed my mind a little bit and I'm going to make sure to put in those quotes and curly's in my code.
The main reason I made this blog because I knew that quotes were considered best practice, but didn't quite understand why on a deep level. So I thought I'd make a provocative post on bash quotes, let the reader know what I know and let the onslaught of comments coming in teach me something new. This is exactly what I was looking for. So, thank you!
In the words of Ellen Ripley:
You forgot one more. When quoting, the value is considered a string. Otherwise it depends on the contents.
This is important for comparison operators as the comparison operators are different for integers (-eq, -gt, -lt, ...) and for strings (==, !=).
So quoting in a comparison makes it less error prone as you know you have a string and can use == to compare.
I mean... When it's a variable that kind of implies that we shouldn't make assumptions about it's contents. You know, because it's variable.