People often stumble when it comes to the various ways strings can be quoted in
Bash. There are two characters which can be used for quoting in bash: "
and
'
; each has its own time and place.
Let’s review some key concepts of bash scripting that we’ve already seen so far to serve as a base for our discussion.
When running the command
$ cp myfile.txt ../mydir
Bash receives two distinct arguments because we separated these arguments by spaces.
There are a variety of characters which have special meaning in Bash. Some of
these characters serve as signals that Bash should replace or expand text
with some other text. These characters in particular are $
, which is used for
environment variables and command substitution, and
`
, which is used as an alternate form of $(...)
($(...) == `...`
).
The way that bash handles strings, referred to as “quoting”, handles both of these problems. Additionally, certain special characters can be explicitly declared as “non-special”, i.e. they should be printed as is. This is called “escaping”.
You can pass a string containing a space as a single argument by enclosing that
string in quotes. Both string characters ("
and '
) will perform this
grouping:
# copies the files "my", "file", "with", "spaces.txt" to "../mydir"
$ cp my file with spaces.txt ../mydir
# copies a single file named "my file with spaces.txt" to "../mydir"
$ cp "my file with spaces.txt" ../mydir
# does the same thing as double quotes
$ cp 'my file with spaces.txt' ../mydir
A similar result can be accomplished with escaping. Just the same as in a
programming language like Java or Python, certain sequences starting with \
have a special meaning, and are referred to as “escape sequences”.
Sequence | Meaning |
---|---|
\$ |
literal $ |
\" |
literal " |
\' |
literal ' |
\` |
literal ` |
\\ |
literal \ |
For a more complete list, see here.
# copies a single file named "my file with spaces.txt" to "../mydir"
$ cp my\ file\ with\ spaces.txt ../mydir
As we’ve already seen, both single and double quotes let you group arguments with spaces. What’s the difference then?
From the bash manual:
Enclosing characters in single quotes (
'
) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.Enclosing characters in double quotes (
"
) preserves the literal value of all characters within the quotes, with the exception of$
,`
,\
, and, when history expansion is enabled,!
.
This means that strings enclosed in double quotes will still have variables expanded and command substitution performed.
$ export myVariable="Hello, world\!"
$ echo myVariable
myVariable
$ echo $myVariable
Hello, world!
$ echo "$myVariable"
Hello, world!
$ echo '$myVariable'
$myVariable
$ ls
myfile.txt
$ echo $(ls)
myfile.txt
$ echo "$(ls)"
myfile.txt
$ echo '$(ls)'
$(ls)