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?
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).
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).