eval does the trick:
Code:
#!/bin/bash
for i in 1 2; do
cmd="date --date=\"$i days ago\""
eval $cmd
done
See also:
Uwe Waldmann - A Guide to Unix Shell Quoting - Common misconceptions
Before the shell executes a command, it performs the following operations (check the manual for details):
1. Syntax analysis (Parsing)
2. Brace expansion
3. Tilde expansion
4. Parameter and variable expansion
5. Command substitution
6. Arithmetic expansion
7. Word splitting
8. Filename expansion
9. Quote removal
It is important to realize that parsing takes place before parameter and command substitution. The result of a step
n is subject to the next steps (
n+), but the preceding steps (
n-) are not re-executed. In other words: after for example variable expansion (step 4) the result is
not re-parsed (step 1).
In the example of the command:
$cmd # cmd="date --date=\"1 days ago\""
the command
date --date=\"$i days ago\" is the result of variable expansion (step 4). Quote removal (step 9) removes the backslashes and turns the command into
date --date="$i days ago". But since parsing (step 1) already has taken place, "1 days ago" is not seen as 1 argument but as 3 separate arguments:
"1,
days and
ago", which gives you the error message:
date: extra operand `ago"'
Try `date --help' for more information.
To force one more run through the parsing/expansion procedure, use:
eval $cmd
Now first
$cmd is expanded (steps 1-9) to
date --date="1 days ago". Then
eval causes the expanded string to be re-parsed again (steps 1-9), resulting in the correct command:
date --date="1 days ago"
Wed Nov 29 08:11:46 CET 2006
Freddy Vulto
http://fvue.nl/wiki/Bash