Standard input and standard output are not commands.
Imagine commands as machines in a factory with an assembly line. Most machines are designed to have one conveyor belt to feed data in and one conveyor belt to feed data out; they are the standard input and the standard output respectively. The standard error is an opening on the side of the machine where it can eject rejects.
+-------+ +------------------+ +------------------+ +------+
| input | | machine A | | machine B | |output|
| reser |=====|<stdin stdout>|=======|<stdin stdout>|=====|bucket|
| ‑voir | → | stderr | → | stderr | → | |
+-------+ +------------------+ +------------------+ +------+
|| ||
The diagram above shows a conveyor belt that goes through two machines. The data comes from the input reservoir on the left, is fed to machine A, then the output is conveyed further to machine B (for which it is input), and machine B's output is deposited in the output bucket on the right.
In unix terms, this is called a pipeline. The metaphor is that of plumbing: a pipe connects machine A to machine B. The shell syntax for the pipeline above is
<input-file.txt commandA | commandB >output-file.txt
The <
redirection symbol tells the shell to connect commandA
's standard input to the file input-file.txt
before launching commandA
. (You can put the redirection before or after the command name.) The >
redirection symbol tells the shell to connect commandB
's standard output to output-file.txt
. The pipe ("|
") symbol in the middle tells the shell to connect commandA
's standard output to commandB
's standard input before launching them.
Commands can have more than one input and more than one output, but that's material for another day.
Bash built-ins are inconsistent and poorly documented.
Here's an example:
$ help command
command: command [-pVv] command [arg ...]
Runs COMMAND with ARGS ignoring shell functions. If you have a shell
function called 'ls', and you wish to call the command `ls', you can
say "command ls". If the -p option is given, a default value is used
for PATH that is guaranteed to find all of the standard utilities. If
the -V or -v option is given, a string is printed describing COMMAND.
The -V option produces a more verbose description.
$ command; echo $?
0
Even without command
the return code $? -eq 0
and there is no error on std err
.
Another one:
$ help disown
disown: disown [-h] [-ar] [jobspec ...]
By default, removes each JOBSPEC argument from the table of active jobs.
If the -h option is given, the job is not removed from the table, but is
marked so that SIGHUP is not sent to the job if the shell receives a
SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all
jobs from the job table; the -r option means to remove only running jobs.
$ disown; echo $?
-bash: disown: current: no such job
1
All the arguments are optional but it returns $? -eq 1
when there are none.
I've even compiled the newest Bash 4.2 and here are my results:
$ help command
command: command [-pVv] command [arg ...]
Execute a simple command or display information about commands.
Runs COMMAND with ARGS suppressing shell function lookup, or display
information about the specified COMMANDs. Can be used to invoke commands
on disk when a function with the same name exists.
Options:
-p use a default value for PATH that is guaranteed to find all of
the standard utilities
-v print a description of COMMAND similar to the `type' builtin
-V print a more verbose description of each COMMAND
Exit Status:
Returns exit status of COMMAND, or failure if COMMAND is not found.
$ command; echo $?
0
There's a new section "Exit Status" and command
is still an optional argument. Even worse than 3.x. The same for other built-ins.
So, you're right. Bash built-ins are a mess and should be fixed.
Best Answer
In
ksh
,bash
andzsh
,time
is not a command (builtin or not), it's a reserved word in the language likefor
orwhile
.It's used to time a pipeline1.
In:
You have special syntax that tells the shell to run that pipe line:
And report timing statistics for it.
In:
It's the same, you're timing the
cmd > output 2> error
command, and the timing statistics still go on the shell's stderr.You need:
Or:
For the shell's stderr to be redirected to
timing-output
before the time construct (again, not command) is used (here to timecmd > output 2> error 3>&-
).You can also run that
time
construct in a subshell that has its stderr redirected:But that subshell is not necessary here, you only need stderr to be redirected at the time that
time
construct is invoked.Most systems also have a
time
command. You can invoke that one by disabling thetime
keyword. All you need to do is quote that keyword somehow as keywords are only recognised as such when literal.But beware the format may be different and the stderr of both
time
andcmd
will be merged intoerror-and-timing-output
.Also, the
time
command, as opposed to thetime
construct cannot time pipelines or compound commands or functions or shell builtins...If it were a builtin command, it might be able to time function invocations or builtins, but it could not time redirections or pipelines or compound commands.
1 Note that
bash
has (what can be considered as) a bug wherebytime (cmd) 2> file
(but nottime cmd | (cmd2) 2> file
for instance) redirects the timing output tofile