4

Got a little bash script like so:

#!/bin/bash
TIME_CMD='/usr/bin/time -f "%E execution time"'

${TIME_CMD} ls

Only problem: doesn't work:

/usr/bin/time: cannot run execution: No such file or directory
Command exited with non-zero status 127
"0:00.00

What am I doing wrong?

Wells
  • 10,415
  • 14
  • 55
  • 85
  • The command works when run directly, i.e. not through setting a variable and then executing it. The problem lies somewhere in that in attempts to execute the bits in the format string, but I wouldn't know why. Perhaps ask on superuser? – moinudin Dec 20 '10 at 21:29
  • I think bash is `fork`-ing a process with `argv[] = { "/usr/bin/time", "-f", "\"%E", "execution", "time\"" }`. But I don't know the syntax to correct the escaping. – aschepler Dec 20 '10 at 21:32

2 Answers2

5

Try making it...

#!/bin/bash
TIME_CMD='/usr/bin/time -f "%E execution time"'

eval "$TIME_CMD ls"

This will utilize bash to re-parse the command string after it has been constructed, so that the quoted argument will be recognized properly.

Amber
  • 507,862
  • 82
  • 626
  • 550
5

Storing commands in variables is generally a bad idea (see BashFAQ #050 for details). The reason it's not working as you expect is that quoting inside variable values is ignored (unless you run it through something like eval, which then tends to lead to other parsing oddities).

In your case, I see three fairly straightforward ways to do it. First, you can use an alias instead of a variable:

alias TIME_CMD='/usr/bin/time -f "%E execution time"'
TIME_CMD ls

Second, you can use a function:

TIME_CMD() { /usr/bin/time -f "%E execution time" "$@"; }
TIME_CMD ls

Third, you can use an array rather than a simple variable:

TIME_CMD=(/usr/bin/time -f "%E execution time")
"${TIME_CMD[@]}" ls

Note that with an array, you need to expand it with the "${array[@]}" idiom to preserve word breaks properly.

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151