Categories
bash double-quotes quotes shell single-quotes

Difference between single and double quotes in Bash

786

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

2

814

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:

3.1.2.2 Single Quotes

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.

3.1.2.3 Double Quotes

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).

4

  • 85

    For anyone who doesn’t know what “interpolate” means: en.wikipedia.org/wiki/String_interpolation

    May 10, 2018 at 17:57

  • 1

    What about when you are using a git_prompt that git provides they suggest using it like this PS1='[\[email protected]\h \W$(__git_ps1 " (%s)")]\$ ', git prompt, 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 2, 2019 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).

    Mar 4, 2019 at 2:08

  • 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.

    Jul 15 at 8:51

514

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.

#ExpressionResultComments
1"$a"applevariables are expanded inside ""
2'$a'$avariables are not expanded inside ''
3"'$a'"'apple''' has no special meaning inside ""
4'"$a"'"$a""" is treated literally inside ''
5'\''invalidcan 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]}"applearray 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'!cmdhistory expansion character '!' is ignored inside ''
20"!cmd"cmd argsexpands to the most recent command matching "cmd"
21$'!cmd'!cmdhistory expansion character '!' is ignored inside ANSI-C quotes

See also:

12

  • 1

    The accepted answer says in the end The special parameters * and @ have special meaning when in double quotes so how come "*" results in *?

    Mar 2, 2018 at 15:40

  • 4

    @Karl-AnderoMere, because they aren’t expanded as parameters in that case at all. "[email protected]" and "$*" are parameter expansions. "@" and "*" are not.

    Apr 21, 2018 at 4:08


  • @CharlesDuffy Thanks, it makes sense now!

    Apr 21, 2018 at 7:46

  • 1

    Csh-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 stackoverflow.com/questions/11816122/echo-fails-event-not-found

    – tripleee

    Dec 17, 2020 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, 2021 at 14:05


249

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

0