views:

171

answers:

2

I'm updating a bash script which serves as a program testing tool. Previously, I had this line in a script working perfectly ($BIN_FILE is set to a relative path to the binary being tested):

$BIN_FILE $BIN_OPTS &> $LOG_FILE

Then I've decided to add some "performance measurements":

time $BIN_FILE $BIN_OPTS &> $LOG_FILE"

This worked perfectly as well, but when running many tests at once, script's output was too crowded with all those "real, user, system". Now I'm passing a second parameter to the script, which causes $TIME variable to have value 'time' assigned to it. However,

$TIME $BIN_FILE $BIN_OPTS &> $LOG_FILE

just doesn't work. The only working option seems to be

eval "$TIME $BIN_FILE $BIN_OPTS &> $LOG_FILE"

but it's ugly.

Why doesn't

$TIME $BIN_FILE $BIN_OPTS &> $LOG_FILE

work? Is there a nicer-looking solution, then the one with eval?

Also, regarding portability - should I use bash's internal 'time', or call GNU /usr/bin/time?

+3  A: 

time is a reserved word in bash. It must be written explicitly because it is parsed before parsing the "simple commands", and therefore before variable substitutions. For example, you cannot use builtin time in this way:

cat long-file | time sort

It has to be:

time cat long-file | sort

and here bash will measure time spend by whole pipeline.

GNU time is a simple binary, so it can be used in the way you mean it... and it can be used in the middle of a pipeline. But it is not always installed, so I guess you'd better use builtin.

I guess you want to omit time in some specific cases and because of that you want variable substitution. If so, you can go with GNU time, eval or some kind of if..fi structure, but you definitely cannot use builtin the way you wanted.

If you want to be more portable, you should use its -p option to get the same output under different implementations. See f.e. OpenGroup's time description. Then whatever implementation you choose, it should behave the same way (as long as it is POSIX-compliant).

liori
+1  A: 

You may find it helpful to use a shorter format for the output of time:

$ /usr/bin/time -f "Real %E" sleep 1
Real 0:01.02
$ TIMEFORMAT="Real %R"
$ time sleep 1        # Bash builtin
Real 1.027

The output of either version of time can be further customized (less so for the Bash builtin).

Dennis Williamson
thanks, I didn't now that besides the only accepted -p option I can use TIMEFORMAT to modify Bash builtin display format.
chronos