In Bash, what are the differences between single quotes (''
) and double quotes (""
)?

- 12,024
- 2
- 30
- 47

- 32,230
- 28
- 81
- 120
-
3See also (a potential cross-site duplicate): [What is the difference between “…”, '…', $'…', and $“…” quotes?](https://unix.stackexchange.com/questions/503013/what-is-the-difference-between-and-quotes) from _Unix & Linux Stack Exchange_. – rugk Feb 27 '19 at 00:35
-
3The title says Bash, but this really applies to any Bourne-compatible shell (classic Bourne shell, POSIX `sh`, `ash`, `dash`, `ksh`, and - with some caveats - `zsh`). – tripleee Jul 22 '20 at 08:26
-
Related: [Is there a syntactical difference between single and double quoted empty strings?](https://stackoverflow.com/q/75373699/8344060) – kvantour Feb 07 '23 at 21:40
7 Answers
Single quotes won't interpolate anything, but double quotes will. For example: variables, backticks, certain \
escapes, etc.
Example:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
The Bash manual has this to say:
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,!
. The characters$
and`
retain their special meaning within double quotes (see Shell Expansions). The backslash retains its special meaning only when followed by one of the following characters:$
,`
,"
,\
, or newline. Within double quotes, backslashes that are followed by one of these characters are removed. Backslashes preceding characters without a special meaning are left unmodified. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an!
appearing in double quotes is escaped using a backslash. The backslash preceding the!
is not removed.The special parameters
*
and@
have special meaning when in double quotes (see Shell Parameter Expansion).

- 39,467
- 16
- 112
- 140

- 51,711
- 9
- 123
- 115
-
97For anyone who doesn't know what "interpolate" means: https://en.wikipedia.org/wiki/String_interpolation – Kellen Stuart May 10 '18 at 17:57
-
1What about when you are using a `git_prompt` that git provides they suggest using it like this `PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '`, [git prompt](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh), according to this shouldn't work. Is there something special about the `PS#` variables? or why does it work if It's not doing the interpolation. – ekiim Mar 02 '19 at 18:34
-
3@ekiim That exact text is set (unchanged) into `PS1`. Try `echo $PS1` to see what I mean. But `PS1` is evaluated before being displayed (see the `PROMPTING` section in the bash manpage). To test this out, try `PS1='$X'`. You will have no prompt. Then run `X=foo` and suddenly your prompt is "foo" (had `PS1` been evaluated when *set* instead of *displayed* you would still have no prompt). – Adam Batkin Mar 04 '19 at 02:08
-
1NB: `$ name='O'Hara'` is not legal but `$ name='O'\''Hara'` works. Even if single quote is not legal between single quote you may escape it by replacing each `'` by `'\''` without space. – Emmanuel Devaux Jul 15 '22 at 08:51
-
In this context, see also: https://stackoverflow.com/questions/16033158/use-of-apostrophe-single-quote-in-a-git-commit-message-via-command-line and https://stackoverflow.com/a/16033290/2153622 within. – nutty about natty Feb 19 '23 at 07:14
The accepted answer is great. I am making a table that helps in quick comprehension of the topic. The explanation involves a simple variable a
as well as an indexed array arr
.
If we set
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
and then echo
the expression in the second column, we would get the result / behavior shown in the third column. The fourth column explains the behavior.
# | Expression | Result | Comments |
---|---|---|---|
1 | "$a" |
apple |
variables are expanded inside "" |
2 | '$a' |
$a |
variables are not expanded inside '' |
3 | "'$a'" |
'apple' |
'' has no special meaning inside "" |
4 | '"$a"' |
"$a" |
"" is treated literally inside '' |
5 | '\'' |
invalid | can not escape a ' within '' ; use "'" or $'\'' (ANSI-C quoting) |
6 | "red$arocks" |
red |
$arocks does not expand $a ; use ${a}rocks to preserve $a |
7 | "redapple$" |
redapple$ |
$ followed by no variable name evaluates to $ |
8 | '\"' |
\" |
\ has no special meaning inside '' |
9 | "\'" |
\' |
\' is interpreted inside "" but has no significance for ' |
10 | "\"" |
" |
\" is interpreted inside "" |
11 | "*" |
* |
glob does not work inside "" or '' |
12 | "\t\n" |
\t\n |
\t and \n have no special meaning inside "" or '' ; use ANSI-C quoting |
13 | "`echo hi`" |
hi |
`` and $() are evaluated inside "" (backquotes are retained in actual output) |
14 | '`echo hi`' |
`echo hi` |
`` and $() are not evaluated inside '' (backquotes are retained in actual output) |
15 | '${arr[0]}' |
${arr[0]} |
array access not possible inside '' |
16 | "${arr[0]}" |
apple |
array access works inside "" |
17 | $'$a\'' |
$a' |
single quotes can be escaped inside ANSI-C quoting |
18 | "$'\t'" |
$'\t' |
ANSI-C quoting is not interpreted inside "" |
19 | '!cmd' |
!cmd |
history expansion character '!' is ignored inside '' |
20 | "!cmd" |
cmd args |
expands to the most recent command matching "cmd" |
21 | $'!cmd' |
!cmd |
history expansion character '!' is ignored inside ANSI-C quotes |
See also:

- 349,597
- 67
- 533
- 578

- 39,467
- 16
- 112
- 140
-
1The accepted answer says in the end `The special parameters * and @ have special meaning when in double quotes` so how come `"*"` results in `*`? – Snackoverflow Mar 02 '18 at 15:40
-
4@Karl-AnderoMere, because they aren't expanded as parameters in that case at all. `"$@"` and `"$*"` are parameter expansions. `"@"` and `"*"` are not. – Charles Duffy Apr 21 '18 at 04:08
-
I just want to point out, that in bash "simple variables" are also arrays, that is `echo $a` is the same as `echo ${a[0]}` in above example – SantaXL Dec 25 '19 at 00:49
-
@codeforester Number 3, you say ' has no special meaning inside ", but according to GNU manual: "The characters ‘$’ and ‘‘’ retain their special meaning within double quotes". and special meaning of ' would be to preserve the literal value of $, and answer should have been $a. Why is it not so? – Lavya Mar 30 '20 at 12:33
-
One more case for the list: `a=apple bash -c 'echo $a'` will output `apple`. Though apparently here `$a` is interpolated inside single quotes, this is in fact enviroment variable expansion by a sub-process. ([details](https://unix.stackexchange.com/a/126947)) – tanius Jun 18 '20 at 13:47
-
3Csh-style history references are probably best turned off; they are not very useful, and turning them off helps you avoid pesky `event not found` error messages for unquoted exclamation marks. See https://stackoverflow.com/questions/11816122/echo-fails-event-not-found – tripleee Dec 17 '20 at 10:00
-
1@codeforester I think that in row 14 result should be `echo hi` surrounded by backtick. Sorry but I could not escape backtick in comment. – piotrekkr Jan 18 '21 at 14:05
-
@piotrekkr: thanks for pointing out. I added a note to rows 13 and 14. I couldn't get Stack Overflow to show the backticks. – codeforester Jan 20 '21 at 07:09
-
NB: `$ name='O'Hara'` is not legal but `$ name='O'\''Hara'` works. Even if single quote is not legal between single quote you may escape it by replacing each `'` by `'\''` without space. – Emmanuel Devaux Jul 15 '22 at 08:55
If you're referring to what happens when you echo something, the single quotes will literally echo what you have between them, while the double quotes will evaluate variables between them and output the value of the variable.
For example, this
#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
will give this:
double quotes gives you sometext
single quotes gives you $MYVAR
Others explained it very well, and I just want to give something with simple examples.
Single quotes can be used around text to prevent the shell from interpreting any special characters. Dollar signs, spaces, ampersands, asterisks and other special characters are all ignored when enclosed within single quotes.
echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'
It will give this:
All sorts of things are ignored in single quotes, like $ & * ; |.
The only thing that cannot be put within single quotes is a single quote.
Double quotes act similarly to single quotes, except double quotes still allow the shell to interpret dollar signs, back quotes and backslashes. It is already known that backslashes prevent a single special character from being interpreted. This can be useful within double quotes if a dollar sign needs to be used as text instead of for a variable. It also allows double quotes to be escaped so they are not interpreted as the end of a quoted string.
echo "Here's how we can use single ' and double \" quotes within double quotes"
It will give this:
Here's how we can use single ' and double " quotes within double quotes
It may also be noticed that the apostrophe, which would otherwise be interpreted as the beginning of a quoted string, is ignored within double quotes. Variables, however, are interpreted and substituted with their values within double quotes.
echo "The current Oracle SID is $ORACLE_SID"
It will give this:
The current Oracle SID is test
Back quotes are wholly unlike single or double quotes. Instead of being used to prevent the interpretation of special characters, back quotes actually force the execution of the commands they enclose. After the enclosed commands are executed, their output is substituted in place of the back quotes in the original line. This will be clearer with an example.
today=`date '+%A, %B %d, %Y'`
echo $today
It will give this:
Monday, September 28, 2015

- 30,738
- 21
- 105
- 131

- 479
- 4
- 8
-
1I like this answer because clearly states `The only thing that cannot be put within single quotes is a single quote`. Just let me add that backticks are deprecated, while $() is POSIX compatible, so you should prefer the latter. – Kiteloopdesign Aug 09 '22 at 18:48
Since this is the de facto answer when dealing with quotes in Bash, I'll add upon one more point missed in the answers above, when dealing with the arithmetic operators in the shell.
The Bash shell supports two ways to do arithmetic operation, one defined by the built-in let
command and the other the $((..))
operator. The former evaluates an arithmetic expression while the latter is more of a compound statement.
It is important to understand that the arithmetic expression used with let
undergoes word-splitting, pathname expansion just like any other shell commands. So proper quoting and escaping need to be done.
See this example when using let
:
let 'foo = 2 + 1'
echo $foo
3
Using single quotes here is absolutely fine here, as there isn't any need for variable expansions here. Consider a case of
bar=1
let 'foo = $bar + 1'
It would fail miserably, as the $bar
under single quotes would not expand and needs to be double-quoted as
let 'foo = '"$bar"' + 1'
This should be one of the reasons, the $((..))
should always be considered over using let
. Because inside it, the contents aren't subject to word-splitting. The previous example using let
can be simply written as
(( bar=1, foo = bar + 1 ))
Always remember to use $((..))
without single quotes
Though the $((..))
can be used with double quotes, there isn't any purpose to it as the result of it cannot contain content that would need the double quote. Just ensure it is not single quoted.
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
Maybe in some special cases of using the $((..))
operator inside a single quoted string, you need to interpolate quotes in a way that the operator either is left unquoted or under double quotes. E.g., consider a case, when you are tying to use the operator inside a curl
statement to pass a counter every time a request is made, do
curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
Notice the use of nested double quotes inside, without which the literal string $((reqcnt++))
is passed to the requestCounter
field.

- 30,738
- 21
- 105
- 131

- 80,270
- 14
- 142
- 161
-
2[Charles Duffy](https://stackoverflow.com/users/14122/charles-duffy) makes a good case [here](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable#comment71378550_10067297) for double quoting `$((...))` as well. It's might be "a little" paranoid and quite unlikely to have `IFS=0` for example, but it certainly is not impossible :) – PesaThe Jan 06 '19 at 21:58
-
There's also the legacy `$[[...]]` syntax but maybe you were right in forgetting it. – tripleee Nov 27 '19 at 19:55
There is a clear distinction between the usage of ' '
and " "
.
When ' '
is used around anything, there is no "transformation or translation" done. It is printed as it is.
With " "
, whatever it surrounds, is "translated or transformed" into its value.
By translation/ transformation I mean the following:
Anything within the single quotes will not be "translated" to their values. They will be taken as they are inside quotes. Example: a=23
, then echo '$a'
will produce $a
on standard output. Whereas echo "$a"
will produce 23
on standard output.
-
This answer is quite confusing and it doesn't add anything on top of the existing good answers. – codeforester Aug 21 '18 at 17:59
-
2This was a short concise answer in my opinion without being overly wordy that was easy for me to comprehend. When saying translation/transformation they are meaning double quotes will expandthe variable where single quotes will not expand the variable. – Apr 09 '19 at 16:19
-
2What you call "transformation or translation" is usually called *interpolation.* The expression `'foo $bar baz'` is simply the literal string `foo $bar baz` whereas `"foo $bar baz"` interpolates the value of the variable `bar` into the string between the literal symbols `foo` and `baz` with spaces in between. – tripleee Feb 24 '21 at 13:19
-
@tripleee I just wanted to explain in simplest terms. And I guess clear explanation is more important than the use of correct "synonym". It sure has helped people without using the word "interpolation". – a_r Feb 25 '21 at 04:45
A minimal answer is needed for people to get going without spending a lot of time as I had to.
The following is, surprisingly (to those looking for an answer), a complete command:
$ echo '\'
whose output is:
\
Backslashes, surprisingly to even long-time users of bash, do not have any meaning inside single quotes. Nor does anything else.

- 3,142
- 3
- 28
- 39