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..

2

2 Answers 2

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 />\(.

1
  • 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, 2013 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.

6
  • 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. Sep 21, 2013 at 17:11
  • @StephaneChazelas Would be nice to see the solution you had in mind Sep 21, 2013 at 17:28
  • 3
    @chhh, cmd 2>&1 > output | tee err >&2 Sep 21, 2013 at 17:31
  • @StephaneChazelas thx! Sep 21, 2013 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, 2013 at 8:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .