What is the difference between echo `date`, echo "`date`", and echo '`date`'?

137,056

Solution 1

`date` will just expand to the output of the date command. However, it removes extra space characters at places where there are more than one consecutive space character in the output. (This is because the command substitution is subject to word splitting, and because of how the echo command handles multiple arguments.)

In "`date`", the double quotes are weak quotes, so they will expand variables (try "$PWD") and perform command substitution. The result of the expansion is passed as a single argument to the echo command, with any consecutive spaces included: that is, word splitting is not performed.

In '`date`', the single quotes are stronger quotes, so they will not allow expansion of variables or command substitution within them.

Refer this link for more explanation.

Edited the first point as correctly pointed by Michael Suelmann in the comment below.

Solution 2

Both

echo `date`

and

echo "`date`"

will display the date. The output from the latter looks like the output from running date by itself.

There's a difference, though: the one surrounded in " quotes " will be sent to to echo as a single argument. The quotes encapsulate the output of the entire command as one argument. Since echo just prints out its arguments in order, with spaces in between, it will basically look the same.

Here's an example of the subtle difference:

echo `date`

produces:

Fri Nov 1 01:48:45 EST 2013

but:

echo "`date`"

produces:

Fri Nov  1 01:48:49 EST 2013

Note that the two spaces after Nov were reduced to one without the quotes. This is because the shell is parsing each space-separated element and sending the result to echo as 6 arguments. When you quote it, echo receives one single argument and the quotes retain the space.

This becomes much more important in commands other than echo. For example, imagine a command foo that wants two arguments: a date, and an email address.

This will work in that scenario:

foo "`date`" [email protected]

But this will confuse the script by sending it 7 arguments:

foo `date` [email protected]

Solution 3

In POSIX shells, `date` is the ancient form of command substitution. The modern syntax is $(date).

In both cases, they expand to the output of date with the trailing newline characters stripped (provided that output doesn't contain NUL characters).

However, when not within double quotes and in list contexts (for instance in arguments to simple commands like echo in your case), that expansion is further subject to:

  1. Word splitting: that is the "output of date with the trailing newline characters stripped" is split according to the current value of the $IFS variable (by default containing space, tab and newline (and NUL with zsh)) into several words.

    For instance, if date outputs Fri 1 Nov 14:11:15 GMT 2013\n (like it often does in an English locale and in a mainland British timezone), and $IFS currently contains :, that will be split into 3 words: Fri 1 Nov 14, 11 and 15 GMT 2013.

  2. Filename generation (aka globbing) (except with zsh): that is, each word resulting from the splitting above is looked for wildcard characters (*, ?, [...] though some shells have more), and expanded to the list of filenames that match those patterns. For instance, if the output of date is ?%? 33 */*/* UVC 3432 (like it often is in Venusian locales and UVC timezone), and $IFS is the default value), then that expands to all the non-hidden 3 character filenames in the current directory whose middle character is %, 33, all the non-hidden files in all the non-hidden subdirectories of all the non-hidden subdirectories of the current directory, UVC and 3432.

That is why:

  1. You should always quote (with double quotes) command substitutions unless you do want either the word splitting or the filename generation performed upon its expansion
  2. If you do want word splitting, then you should set $IFS to the characters you want to split on.
  3. If you do want word splitting but not filename generation, you need to issue a set +f to disable it.

The single quotes quote everything so cause the backtick characters to be taken literally.

Example (using -x makes it easier to see what's going on):

$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri  1 Nov 14' 42 '33 GMT 2013'
Fri  1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri  1 Nov 14:42:41 GMT 2013'
Fri  1 Nov 14:42:41 GMT 2013

bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS     # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432

If the output contains NUL characters, then the behaviour varies from shell to shell: some remove them, some truncate the output at the first NUL character, zsh preserves them but note that anyway external commands cannot take arguments containing NULs

Share:
137,056
John
Author by

John

Updated on September 18, 2022

Comments

  • John
    John almost 2 years

    What is the difference between these three commands?

    echo `date`
    echo "`date`"
    echo '`date`'
    

    I am confused on what the differences actually are. I think that when the ' are around it means that it is a string, therefore echo would literally output the string date instead of displaying the date?

  • John
    John over 10 years
    What exactly is the ` character that is surrounding date called? If I am understanding correctly, meta characters will not work in single quotations?
  • John
    John over 10 years
    If I am understanding correctly, meta characters will not work in single quotations?
  • Jim Stewart
    Jim Stewart over 10 years
    The ` is often called a "backtick" in that scenario and various Unix documentation/books. It's not actually being used as a Unicode grave accent when it's on its own like that, even though that's the name of the symbol. And you're correct that no expansion of metacharacters/expressions will occur if you surround it with single quotes.
  • jlliagre
    jlliagre over 10 years
    Your first statement is incorrect as the output might be slightly different depending on the date or locale. Only the second command will output the same thing as the bare date command.
  • jlliagre
    jlliagre over 10 years
    You are self contradicting in your first sentence. The first and second form won't always output the same thing as you demonstrate later.
  • Chirag Bhatia - chirag64
    Chirag Bhatia - chirag64 over 10 years
    @jlliagre: Can you provide an example where the first statement's output would be different than the bare command?
  • Michael Suelmann
    Michael Suelmann over 10 years
    @Chirag64: if the output of date contains two spaces next to each other, echo `date` will only output one. With quotes you'll get both.
  • Bonsi Scott
    Bonsi Scott over 10 years
    "Fri Nov 1 15:19:00 CET 2013", "Fri Nov 1 15:19:00 CET 2013" and "date"
  • Izkata
    Izkata over 10 years
    @BonsiScott The extra space between "Nov" and "1" is removed in HTML as well ;)
  • fpmurphy
    fpmurphy over 6 years
    There is no such thing as an actual "POSIX shell". There are shells that can conform to the various relevant POSIX standards by using a limited subset of their functionality.