Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question

4 Answers 4

`date` will just return the output of the date command. However, it removes extra space characters at places where there are more than one consecutive space characters in the output.

In "`date`", the double quotes are weak quotes, so they will expand variables (try "$PWD") and perform command substitution.

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.

share|improve this answer
    
What exactly is the ` character that is surrounding date called? If I am understanding correctly, meta characters will not work in single quotations? –  John Nov 1 '13 at 6:27
1  
Its called a Grave accent –  Chirag64 Nov 1 '13 at 6:30
    
If I am understanding correctly, meta characters will not work in single quotations? –  John Nov 1 '13 at 6:46
7  
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. –  Jim Stewart Nov 1 '13 at 6:55
1  
@BonsiScott The extra space between "Nov" and "1" is removed in HTML as well ;) –  Izkata Nov 1 '13 at 15:53

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`" joeuser@example.com

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

foo `date` joeuser@example.com
share|improve this answer
2  
You are self contradicting in your first sentence. The first and second form won't always output the same thing as you demonstrate later. –  jlliagre Nov 1 '13 at 8:10
    
Thanks. I've changed up the wording to make it more clear. –  Jim Stewart Nov 1 '13 at 16:13

With `date` you get the output of date split into multiple words, because word splitting is done after command substitution.

With "`date`" you get the output of date as one word/parameter as there is command substitution between double quotes, but the output is not parsed further. The same is valid with variable expansion like "$i" in my example below.

With '`date`' you get a literal `date` as there is no command substitution between single quotes.

Perhaps the differences of the 3 forms will be more visible this way:

> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013

> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013

> for i in '`date`'; do echo "$i"; done
`date`
share|improve this answer

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 IFS     # get the default behaviour
+ unset 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|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.