5

I'm looking at this script mysql backup script and I don't understand what is the reason for using both backticks and double quotes around command names?

379 WHICH="`which which`"
380 AWK="`${WHICH} gawk`"
381 LOGGER="`${WHICH} logger`"
382 ECHO="`${WHICH} echo`"
383 CAT="`${WHICH} cat`"
384 BASENAME="`${WHICH} basename`"
385 DATEC="`${WHICH} date`"
386 DU="`${WHICH} du`"
387 EXPR="`${WHICH} expr`"
388 FIND="`${WHICH} find`"
389 RM="`${WHICH} rm`"
390 MYSQL="`${WHICH} mysql`"
391 MYSQLDUMP="`${WHICH} mysqldump`"
392 GZIP="`${WHICH} gzip`"
393 BZIP2="`${WHICH} bzip2`"
394 CP="`${WHICH} cp`"
395 HOSTNAMEC="`${WHICH} hostname`"
396 SED="`${WHICH} sed`"
397 GREP="`${WHICH} grep`"

Update:

Is

"`${WHICH} gawk`"

pretty much the same as

"${${WHICH} gawk}"
Stann
  • 2,209

3 Answers3

10

WHICH="`which which`" is exactly equivalent to WHICH=`which which` or to WHICH=$(which which) or to WHICH="$(which which)". All of these run the command which which, and capture its output (as a string) into the variable WHICH, stripping off any final newline from the output. Similarly, AWK="`${WHICH} gawk`" could be written AWK=`$WHICH gawk`.

Normally, command substitutions (`command` or $(command)) should be surrounded by double quotes, in case the result contains whitespace or shell wildcards (*?[\). This is because the result of command substitutions, like variable substitutions ($foo or ${foo}), undergoes word splitting and filename generation (a.k.a. globbing). However, this does not apply to simple variable assignments: since the context requires a single word, the result of the substitution is taken as-is. So assignments are an exception to the general rule that you should double-quote variable and command substitutions. (Note that this exception does not extend to export var="$value", which does require the double quotes.) But it's a reasonable shell programming practice to always the double quotes — omit them only if you know you must, rather than using them only if you know you must.

In the (unlikely) case which which returns a path with spaces or wildcards, ${WHICH} should be double-quoted in the lines below, i.e. one of

AWK="`"${WHICH}" gawk`"
AWK=`"${WHICH}" gawk`
AWK="$("${WHICH}" gawk)"
AWK=$("${WHICH}" gawk)

(Using $(…) is recommended over `…`, because of the difficulty of getting the nested quoting right inside `…`. However very old shells don't recognize $(…), so `…` is needed for scripts that must run on older systems.)

See also $VAR vs ${VAR} and to quote or not to quote

  • mmm. Correct me if I'm wrong. So looks like original script author didn't need to create alias for ECHO - since it's a built bash command? - right? – Stann Apr 19 '11 at 02:41
  • 4
    @Andre: Yes, ECHO is completely useless. But then all the calls to which here are useless, because all the script ever does is call the commands, which would look up the PATH anyway. The quoting is also off: there are double quotes in the definitions of these variables, where they don't make a difference, but not when using the variables, where it would (and sometimes they're even evaled). You mustn't call this script with any special character in a command name (or in $PASSWORD, but using that is a bad idea anyway). – Gilles 'SO- stop being evil' Apr 19 '11 at 07:06
  • yeah -I was scratching my head about those evals as well:) Also - regular variables should be lowercased to avoid any collisions with internal shell variables. And they are uppercased everywhere in that script. um.. oh well. Things like this really hinder bash beginners like myself. So - thanks for your help! – Stann Apr 19 '11 at 07:50
  • IMHo - that script is a bit over-engineered for what it does, - mysql dbs backup, - -would you agree? – Stann Apr 19 '11 at 07:55
1

In case the backticks return a string with spaces in it. The quotes ensure that the complete, single value is assigned to the variable.

Keith
  • 7,914
  • 1
  • 28
  • 29
  • 5
    While using double quotes around command substitutions is a good idea in general, this is one of the few cases where they are not necessary: variable assignments always result in a single word, with no word splitting or filename generation performed on the result of the substitution. – Gilles 'SO- stop being evil' Apr 18 '11 at 21:21
  • 1
    That may be true, but the question was why does one particular script do it, and I'm sure that's what the original author had in mind. Right or wrong, that would be the reasoning. Because, as you said, it is generally a good idea and does no harm in this context. – Keith Apr 18 '11 at 22:32
  • 1
    Which is, why the advice is bad. If you use them, when they are benficial, and omit them, when not, you encourage the learning of the distinction, which is beneficial itself. – user unknown Apr 19 '11 at 00:17
  • 1
    Some of us have better things to do with our time than learn shell minutiae. Doing it the safe way, that has no downside, is fine advice. – Keith Apr 19 '11 at 00:56
0

The backtick operator means "replace the area between the backticks with the output of the command found inside backticks. The double quotes are so, if that output contains spaces, the variable in question will be set to the full result and not just everything up to the first whitespace.

E.g., if for some reason your grep command is '/usr/local/bin/real grep', after the execution of,

GREP=`which grep`

GREP would contain "/usr/local/bin/real"

Whereas with,

GREP="`which grep`"

GREP would contain "/usr/local/bin/real grep".

It's quite unlikely any of the paths of these commands would contain whitespace, but it's general good practices in shell scripting to always use double quotes when assigning to a variable.

tak
  • 186
  • 3
    While using double quotes around command substitutions is a good idea in general, this is one of the few cases where they are not necessary: variable assignments always result in a single word, with no word splitting or filename generation performed on the result of the substitution. – Gilles 'SO- stop being evil' Apr 18 '11 at 21:20
  • 1
    After running a test script it seems you're right. After executing, TEST=echo testing 123, $TEST contains "testing 123". I would still say that it's a good idea to include the double quotes on variable assignment in any case though. – tak Apr 18 '11 at 22:06