Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First, with some exceptions, redirections generally occur at the point they are written. They are removed from the command-and-argument sequence; only the remaining, non-redirection, words participate. Thus:</p> <pre><code>3&gt;&amp;1 foo 1&gt;&amp;2 arg1 2&gt;&amp;3 arg2 3&gt;&amp;- arg3 </code></pre> <p>runs <code>foo arg1 arg2 arg3</code> with stdout and stderr swapped, because:</p> <ol> <li><code>3&gt;&amp;1</code> makes a copy (more precisely, a <code>dup2</code>) of fd 1 (stdout) on fd 3</li> <li><code>1&gt;&amp;2</code> makes a copy of fd 2 (stderr) on fd 1 (so now stdout and stderr both go wherever they were going)</li> <li><code>2&gt;&amp;3</code> makes a copy of fd 3 (saved original stdout) on fd 2 (stderr)</li> <li><code>3&gt;&amp;-</code> closes fd 3.</li> </ol> <p>(The notable exception is that piped output "happens first", even though the pipe symbol is at the end of the simple-command part.)</p> <p>Second, as pje noted, <code>time</code> is a bash built-in. <code>time foo</code> runs the command, then prints the time summary to bash's stderr. The <code>time</code> keyword is effectively removed first, then the remaining command sequence is handled as usual. (This applies even if the command is a pipeline: <code>time</code> times the entire pipeline.)</p> <p>In this case, the command sequence is one simple command, with redirections:</p> <pre><code>2&gt;&amp;1 sh 2&gt;&amp;1 -c ... &gt; file </code></pre> <p>Each redirection happens at the point it is written, and the remaining sequence is:</p> <pre><code>sh -c ... </code></pre> <p>The redirections are:</p> <ol> <li>send stderr to wherever stdout is currently going</li> <li>send stderr to stdout, again (this has no new effect)</li> <li>send stdout to <code>file</code>.</li> </ol> <p>so <code>sh -c</code> is run with its stderr going to your stdout, and its stdout going to file <code>file</code>. As you note, <code>dd</code> prints its output to (its) stderr, which is <code>sh -c ...</code>'s stderr, which is your stdout.</p> <p>If you run:</p> <pre><code>time 2&gt;file dd if=/dev/zero of=ddfile bs=512 count=125 </code></pre> <p>you will get <code>time</code>'s stderr output on your stderr (e.g., screen), and <code>dd</code>'s stderr on file <code>file</code>. (This happens no matter how far right you slide the <code>2&gt;file</code> part, as long as it remains part of the simple-command.)</p> <p>If you try:</p> <pre><code>2&gt;file time ... </code></pre> <p>you will find <code>time</code>'s output redirected, but this defeats the built-in <code>time</code> entirely, running <code>/usr/bin/time</code> instead. To get bash's built-in to fire, <code>time</code> has to be up front. You can make a sub-shell:</p> <pre><code>(time ...) 2&gt;file </code></pre> <p>or a sub-block as <a href="https://stackoverflow.com/a/18753722/1256452">pje illustrated</a>:</p> <pre><code>{ time ...; } 2&gt;file </code></pre> <p>(the syntax is clumsier with the sub-block as white space and/or semicolons are needed, but it avoids a <code>fork</code> system call).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload