Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sh: time: command not found

1,289 views
Skip to first unread message

Rafael Martins de Souza

unread,
Apr 30, 2012, 7:30:36 AM4/30/12
to
When I execute sh -c "time <command>" it works but sh -c "time -p <command>" doesn't even though writing just time -p <command> works.

sh is a symlink to bash 4.2.24.

Could someone clarify to me why this happens?

Thanks in advance

Ersek, Laszlo

unread,
Apr 30, 2012, 9:37:55 AM4/30/12
to
I suspect this is a bash bug or at least an idiosyncrasy.

Command Search and Execution:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01

time - time a simple command:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/time.html

2.4 Reserved Words
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_04

From my the bash manual:

"If bash is invoked with the name sh, it tries to mimic the startup
behavior of historical versions of sh as closely as possible, while
conforming to the POSIX standard as well. [...] When invoked as sh, bash
enters posix mode after the startup files are read."

The SUS (links above are to v4) enables the "time" utility to be
implemented as a regular built-in or shell function (Command Search and
Execution, 1/d/i/a) or with execve() (1/d/i/b). "time" cannot be a special
built-in, according to the standard (the section listing those doesn't
list "time".)

However bash implements "time" as a "shell keyword":

$ type -a time
time is a shell keyword
time is /usr/bin/time

The standard generally avoids the term "keyword"; the single example I
managed to find is "[...] while, until, or if keyword [...]" in the
description of the "set" special built-in. Those tokens are actually
defined under "Reserved Words" (see link above). Therefore we can assume
that the "shell keyword" bash term corresponds to "reserved word". Indeed:

$ type -a for then esac
for is a shell keyword
then is a shell keyword
esac is a shell keyword

So, bash implements "time" as a reserved word (which looks quite
non-conformant), and it starts to act upon it way before it gets to
Command Search and Execution (same as if you typed a "for" loop -- you
don't expect the shell to search PATH for an executable named "for", even
in case there's one).

In non-POSIX mode (when you invoke it as "bash" without further options
and interactively), it supports "time -p" (quite unusual for a reserved
word to take an option). When you run bash in POSIX mode, it stops
supporting the -p option of this "reserved word", but you can't really
complain about that, because "time" being a reserved word is broken from
the start.

You can do two things:

(1) Use dash, which -- in my understanding -- targets POSIX as a priority.
Dash chooses the 1/d/i/b way ("the shell executes the utility in a
separate utility environment"), ie. you'll have to install GNU time
("/usr/bin/time" in the above listing from my machine).

(2) Summon 2.2 Quoting:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02

"Quoting can be used to [...] prevent reserved words from being recognized
as such [...]"

Just use 'time' (with quotes) or \time whenever you mean to invoke the
time utility, and then bash will always defer to the 1/d/i/b way (and
you'll always need GNU time on GNU/Linux). In other, conforming
environments, spelling it 'time' or \time won't have any side effects, so
one could argue "always write 'time'".

BTW the "--" end-of-options delimiter reproduces this in an even more
telling way (with or without -p). The time utility conforms to the Utility
Syntax Guidelines, and "--" is Guideline 10.

$ time -p -- sleep 1
bash: --: command not found
real 0.00
user 0.00
sys 0.00

$ 'time' -p -- sleep 1
real 1.00
user 0.00
sys 0.00

Laszlo

Geoff Clare

unread,
May 2, 2012, 8:34:44 AM5/2/12
to
Ersek, Laszlo wrote:

> The SUS (links above are to v4) enables the "time" utility to be
> implemented as a regular built-in or shell function (Command Search and
> Execution, 1/d/i/a) or with execve() (1/d/i/b). "time" cannot be a special
> built-in, according to the standard (the section listing those doesn't
> list "time".)
>
> However bash implements "time" as a "shell keyword":

As do ksh88 and ksh93. This is an acknowledged defect in POSIX.
(The POSIX shell was based on ksh88, so it should have allowed
this way of implementing "time" in the original standard.)

See http://austingroupbugs.net/view.php?id=267 for the *long* list
of changes that are planned to address this.

--
Geoff Clare <net...@gclare.org.uk>

0 new messages