user3791276
user3791276

Reputation: 79

Bash variable expansion can't be combined with time command

I was writing a small shell script in bash to measure the speed of several executables using the time command. Because I wanted to time several different programs, to avoid repeating myself I saved the time command and the format string I wanted and tried to use variable expansion (testing the performance of ls as an example):

#!/usr/bin/env bash

timer="/usr/bin/time -f 'elapsed time: %E' --"
$timer ls 1>/dev/null

The time command is supposed to use the -- to separate its options (in this case a format string) from the command it's supposed to time. However, in this script time insists on trying to execute my format string and fails with

/usr/bin/time cannot run time:: No such file or directory
Command exited with non-zero status 127
'elapsed

But if I put the whole command on one line with no variable expansion it correctly recognizes the format string and executes ls:

#!/usr/bin/env bash

/usr/bin/time -f 'elapsed time: %E' -- ls 1>/dev/null

produces "elapsed time: 0:00.00"

I ended up just typing out the whole command on each line to get it to run, but I was curious if anyone could explain why variable expansion doesn't work here.

Upvotes: 0

Views: 90

Answers (2)

that other guy
that other guy

Reputation: 123450

The data in $timer is split on $IFS (spaces), and used as separate arguments. It is not expanded and then evaluated as bash code.

Your command $timer ls is therefore equivalent to:

"/usr/bin/time" "-f" "'elapsed time:" "%E'" "--" "ls"

The correct way to do this in your case is using a function:

timer() {
  /usr/bin/time -f 'elapsed time: %E' -- "$@"
}
timer ls

PS: This problem is automatically pointed out by shellcheck.

Upvotes: 2

anubhava
anubhava

Reputation: 785058

You need to use a BASH array to store command line:

timer=(/usr/bin/time -f 'elapsed time: %E' --)
"${timer[@]}" ls

Upvotes: 1

Related Questions