2026/02/06

Timing multiple commands with time

time vs /bin/time

Bash implements time command:
$ type time
time is a shell keyword

$ time date
Thu  5 Feb 23:05:56 GMT 2026

real	0m0.001s
user	0m0.000s
sys	0m0.001s
Which is different from /bin/time:
$ type /bin/time 
/bin/time is /bin/time

$ /bin/time date
Thu  5 Feb 23:06:00 GMT 2026
0.00user 0.00system 0:00.00elapsed 90%CPU (0avgtext+0avgdata 2016maxresident)k
0inputs+0outputs (0major+91minor)pagefaults 0swaps

In 2026, the above /bin/time default output looks like corrupted gibberish, rather than something formatted nicely for humans to read. Its reported metrics "inputs", "outputs", "avgtext", "avgdata", "swaps" are little more than meaningless and worthless noise in 2026.

Yet, the full report of /bin/time is unmatched by its cheap-and-quick shell keyword knock-offs:

$ /bin/time -v date
Thu  5 Feb 23:06:26 GMT 2026
	Command being timed: "date"
	User time (seconds): 0.00
	System time (seconds): 0.00
	Percent of CPU this job got: 86%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 2016
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 91
	Voluntary context switches: 1
	Involuntary context switches: 0
	Swaps: 0
	File system inputs: 0
	File system outputs: 0
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0

/bin/time -v report is most verbose. With those "Average" metrics with 0 values being in there only to avoid breaking some still existing obsolete software.

/bin/time -p does match the bare output of shell keyword time to prevent POSIX aficionados typing all that extra-verbose POSIX-compliant /bin/sh codes invoking time -p from rioting.

From engineering perspective, it is most desirable to see some of the key metrics /bin/time -v reports above, which shell keyword time does not report. But without having to type anything more beyond the already aggravating enough /bin/time. And that's where environment variable TIME enters ~/.bashrc (which should be always sourced by ~/.bash_profile):

# put this line into /etc/environment or your ~/.bashrc
$ export TIME='Elapsed time %E, user %Us, system %Ss, CPU %P, RSS %MkB, exit-status %x.\n'

With environment variable TIME set as above:

$ /bin/time date
Thu  5 Feb 23:06:33 GMT 2026
Elapsed time 0:00.00, user 0.00s, system 0.00s, CPU 89%, RSS 2016kB, exit-status 0.

Making /bin/time report in one line the wall/user/system times, which shell keyword time reports in multiple lines, most wastefully. As well as CPU and RAM usage, and the exit status.

In other words, setting environment variable TIME makes /bin/time output immediately more useful, insightful and helpful.

Timing multiple commands

Timing one command is easy:
$ /bin/time date
Thu  5 Feb 23:06:27 GMT 2026
Elapsed time 0:00.00, user 0.00s, system 0.00s, CPU 83%, RSS 2016kB, exit-status 0.

Timing multiple commands is harder because /bin/time must start before the first command and terminate after the last. Just prefixing any command line with /bin/time only times a command before the next bash control operator -- a token that performs a control function, ... one of the following symbols: || & && ; ;; ;& ;;& ( ) | |&

For shell pipelines, bash has to create the pipeline consumer process first (the process on the right of pipeline binary operator), and terminate it last. Wrapping multiple commands into a compound list { cmds ; } (wrapping with extra `{`, `;`, `}` tokens), and piping the compound list into that pipeline consumer process | /bin/time cat ends up measuring time from just before the compound list started executing till just after it terminated.

pipefail option must be explicitly enabled to fail on errors earliest instead of ignoring errors silently.

Timing multiple commands:

$ { uname -a && echo && cat /proc/cmdline && echo && make --version ; } | /bin/time cat
Linux supernova2 6.8.0-94-generic #96-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan  9 20:36:55 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux

BOOT_IMAGE=... root=UUID=... ro transparent_hugepage=always mitigations=off iommu=pt amdgpu.aspm=0

GNU Make 4.4.1
...
Elapsed time 0:00.00, user 0.00s, system 0.00s, CPU 0%, RSS 1920kB, exit-status 0.

No comments:

Post a Comment