11

I need to log stdout and stderr to logfiles, but only show the error messages on screen. I can do this with:

cp -rpv a/* b 1> copyLog.txt 2> >(tee copyError.txt >&2) 

Which I found somewhere in the web.

I just want to know how this >(tee copyError.txt >&2) thing is called? I can't google for it, since Google ignores characters like angle brackets and the parentheses..

11

From man bash:

   Process Substitution
       Process substitution is supported  on  systems  that  support
       named  pipes  (FIFOs)  or  the  /dev/fd method of naming open
       files.  It takes the form of <(list) or >(list).  The process
       list  is  run with its input or output connected to a FIFO or
       some file in /dev/fd.  The name of this file is passed as  an
       argument  to  the current command as the result of the expan‐
       sion.  If the >(list) form is used, writing to the file  will
       provide  input  for  list.   If the <(list) form is used, the
       file passed as an argument should be read to obtain the  out‐
       put of list.

You can search manpages by pressing / and then typing your search string, which is a good way of finding information like this. It does of course require that you know in which manpage to search :)

You have to quote the ( though, because it has a special meaning when searching. To find the relevant section in the bash manpage, type />\(.

  • I do a lot of bash, so I did a man bash > bashman.txt and made it read only. Now, I can load bashman.txt into another window in my text editor (read only) and use all the editor's facilities for searching and copying and pasting. – Joe Sep 27 '13 at 21:54
8

>(tee copyError.txt >&2) is actually a few different features:

  • >(...) is called 'process substitution'. It creates a named pipe file in /dev/fd and writing to that file will provide input to the process in the parentheses.

  • > : In general, this is called 'output redirection' and allows you to send standard output (> or 1>) or standard error (2>) to a file or process. >&2 is output redirection but in this case, the output of tee is sent to standard error (that's what &2 is, &1 is standard output)

  • Without >, parentheses (()) will start a subshell. Running commands in parentheses will spawn another shell which will only exist for as long as those commands are running. You can see how this works if you declare a variable in the subshell:

    $ foo='Tom';(foo='Dick'; echo "Sub: $foo"); echo "Orig: $foo"
    Sub: Dick
    Orig: Tom
    

    As you can see, the $foo that was defined in the subshell is separate from the one defined in the parent shell.

  • 4
    No >(...) is not a redirection. >(...) is expanded to a file name. If you want to redirect output to that, you need > >(...) but >(...) is more generally used where redirections can't be used. The OP's command can be achieved with traditional pipes, there's not need for process substitution there. – Stéphane Chazelas Sep 21 '13 at 17:11
  • @StephaneChazelas Would be nice to see the solution you had in mind – Dmitry Avtonomov Sep 21 '13 at 17:28
  • 3
    @chhh, cmd 2>&1 > output | tee err >&2 – Stéphane Chazelas Sep 21 '13 at 17:31
  • @StephaneChazelas thx! – Dmitry Avtonomov Sep 21 '13 at 17:34
  • The first half of this answer is wrong, or at least highly misleading; it's true that > can denote output-redirection and that () can denote a subshell, but >(...) is actually a single, unitary feature that does not consist of > and (). – ruakh Sep 22 '13 at 8:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.