Jason S
Jason S

Reputation: 1554

Using quotes within command substitution

I don't understand why this works

dateCMD=$(date -d "4 hours ago")
echo $dateCMD
Tue Oct 18 02:20:34 AEDT 2016

and this works

dateCMD="date"
$dateCMD
Tue Oct 18 06:23:19 AEDT 2016

But not this

dateCMD='date -d "4 hours ago"'
$($dateCMD)
date: extra operand ‘ago"’

How can I get this last case to work?

Upvotes: 2

Views: 64

Answers (3)

Jason S
Jason S

Reputation: 1554

To get the last case to work, you can use eval

Of course you should not use eval on any user input without completely validating that input.

dateCMD='date -d "4 hours ago"'
eval $dateCMD

Upvotes: 0

chepner
chepner

Reputation: 532268

Short answer: you don't want to do that. Use a function instead.

dateCMD () {
  date -d "4 hours ago"
}

dateCMD

Long answer: quotes in the value of a parameter are not "syntactic" quotes; they are just regular data. When you write

dateCMD='date -d "4 hours ago"'
$($dateCMD)

It is evaluated as follows:

  1. $dateCMD expands to date -d "4 hours ago"
  2. The expansion is split into the words date, -d, "4, hours, and ago". The quotes are not treated specially.
  3. The first word, date, is treated as the command with the rest of the words passed as distinct arguments.
  4. date treates "4 as the argument to the -d option. Since date takes only one additional positional argument (the format string), it takes hours as that argument, then complains that ago is an extra operand.

Upvotes: 6

anubhava
anubhava

Reputation: 786091

Use BASH array to make it work:

dateCMD=(date -d "4 hours ago")
"${dateCMD[@]}"
Mon Oct 17 11:38:54 EDT 2016

I was typing explanation on your quoting problem but then I noticed very well explained answer from @chepner so avoided adding redundant information in my answer.

Upvotes: 2

Related Questions