1. Introduction

As beginners in the Linux ecosystem, we may come across arguments in several commands that we read about online. Sometimes, we wrap these arguments in double-quotes, sometimes in single-quotes, and sometimes we don’t wrap them in quotes at all. In this article, we’ll look at various scenarios where different quotes may be used or omitted and understand how quoting works.

2. Strings With Whitespace

In scenarios when we have literal strings or arguments that have whitespace in them, we may use either single or double quotes to wrap the whole string to have it treated as if it were a single argument. We can try this using the expr command:

$ expr length "hello world"
11
$ expr length 'hello world'
11
$ expr length hello world
expr: syntax error: unexpected argument ‘world’

When we use single quotes or double quotes, “hello world” is treated as a single argument, and the length evaluates to 11. When we omit the quotes, “hello” and “world” are treated as separate arguments, and the command throws an error because it’s expecting only one argument for the length operation.

3. Controlling Variable Interpolation

Variable interpolation happens when we use double quotes or omit quotes. When we need to suppress variable interpolation, we wrap the arguments in single quotes. We can see this in action using a few examples:

$ a=hello
$ b=world
$ echo $a
hello
$ echo "$a"
hello
$ echo "$a $b"
hello world
$ echo '$a $b'
$a $b

In the examples above, we have defined two variables, ‘a’ and ‘b’, and we see their values are substituted when we use double quotes or omit the quotes. When we use single quotes, the variable names are printed verbatim because no substitution happens.

4. Command Substitutions

Similar to variable interpolation, command substitution works only when we do it inside double quotes or omit the quotes. Single quotes will take the argument verbatim. Let’s try out some commands to see how this works:

$ echo "$(ls /usr/share/dict)"
american-english
british-english
README.select-wordlist
words
words.pre-dictionaries-common
$ echo $(ls /usr/share/dict)
american-english british-english README.select-wordlist words words.pre-dictionaries-common
$ echo '$(ls /usr/share/dict)'
$(ls /usr/share/dict)

From the above examples, we see that when we use double quotes or omit the quotes, the command enclosed in the braces is executed, and the result is printed. When we use single quotes, the command is not executed, but the argument is printed verbatim.

5. Controlling File Globbing

We can use single or double quotes to suppress file globbing. If we need file globbing to work, we need to omit the quotes:

$ cat *
file1 contents
file2 contents
file3 contents
$ cat "*"
cat: '*': No such file or directory
$ cat '*'
cat: '*': No such file or directory
$ cat "my dir/"*
file1 contents
file2 contents
file3 contents
$ cat my dir/*
cat: my: No such file or directory
cat: 'dir/*': No such file or directory

From the above examples, we also note that we can enclose whitespace in quotes and put wildcard characters outside the quotes to perform globbing. This works with both single and double quotes.

6. Protecting Quotes and Special Characters

We may use single quotes to protect double quotes and vice-versa:

$ echo he'll'o
hello
$ echo he"ll"o
hello
$ echo 'he"ll"o'
he"ll"o
$ echo "he'll'o"
he'll'o

In the above examples, we see that the quotes in the string are retained only when the whole string is wrapped in quotes. We also have the option of including a $ sign before the single quotes to have escape sequences interpreted according to their meanings. Further, we can use this to protect single quotes as well as double quotes in the same string:

$ echo "hello\nworld"
hello\nworld
$ echo 'hello\nworld'
hello\nworld
$ echo $'hello\nworld'
hello
world
$ echo $'\'single quoted text\' and "double quoted text"'
'single quoted text' and "double quoted text"

7. Controlling Word Splitting

To perform word splitting, we need to omit quotes. When we add quotes, splitting does not occur, and the whole string is processed as one unit:

$ for word in one two three; do echo $word; done
one
two
three
$ for word in "one two three"; do echo $word; done
one two three
$ for word in 'one two three'; do echo $word; done
one two three

In the first case, the loop runs thrice because word splitting happens and yields three words, whereas in the latter cases, the loop runs only once with the entire string as the value.

8. Conclusion

In this article, we looked at various effects of three types of quoting arguments and also what happens when no quotes are used. Let’s summarize the key points below for quick reference:

Scenario

Double Quotes

Single Quotes

No Quotes

Whitespaces Allowed in Argument

Yes

Yes

No

Variable Interpolation

Yes

No

Yes

Command Substitutions

Yes

No

Yes

File Globbing

No

No

Yes

Word Splitting

No

No

Yes

Quote Protection

Single Quotes

Double Quotes

None

Note that we can use shell quoting along with escape sequences if we need to protect both single and double quotes in a string.