What is the difference between echo `date`, echo "`date`", and echo '`date`'?
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:
-
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 withzsh
)) into several words.For instance, if
date
outputsFri 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
and15 GMT 2013
. -
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 ofdate
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
and3432
.
That is why:
- 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
- If you do want word splitting, then you should set
$IFS
to the characters you want to split on. - 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
John
Updated on September 18, 2022Comments
-
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 over 10 yearsWhat exactly is the ` character that is surrounding date called? If I am understanding correctly, meta characters will not work in single quotations?
-
John over 10 yearsIf I am understanding correctly, meta characters will not work in single quotations?
-
Jim Stewart over 10 yearsThe ` 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 over 10 yearsYour 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 over 10 yearsYou 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 over 10 years@jlliagre: Can you provide an example where the first statement's output would be different than the bare command?
-
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 over 10 years"Fri Nov 1 15:19:00 CET 2013", "Fri Nov 1 15:19:00 CET 2013" and "
date
" -
Izkata over 10 years@BonsiScott The extra space between "Nov" and "1" is removed in HTML as well ;)
-
fpmurphy over 6 yearsThere 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.