Tar to pipe but keep -v verbose output separate from STDERR

iokshtar

A normal tar command

tar cvf foo.tar ./foo >foo.out 2>foo.err

has three output IO streams

  • archive data to foo.tar
  • list of filenames to STDOUT (redirected into foo.out)
  • error messages to STDERR (redirected into foo.err)

I can then inspect foo.err for error messages without having to read through the list of filenames.

if I want to do something with the archive data (pipe it through netcat or a special compression program) I can use tar's -f - option thus

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

But now my list of filenames is mixed in with my error messages because tar's -v output obviously can't go to STDOUT (that's where the archive data flows) so tar cleverly writes that to STDERR instead.

Using Korn shell, is there a way to construct a command that pipes the archive stream to another command but still capture the -v output separately from any error messages.

Best Answer

If your system supports /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

Which with AT&T implementations of ksh (or bash or zsh) you could write using process substitution:

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

That's doing exactly the same thing except that this time, the shell decides of which file descriptor to use instead of 3 (typically above 9). Another difference is that this time, you get the exit status of tar instead of squish. On systems that do not support /dev/fd/n, some shells may resort to named pipes for that feature.

If your system doesn't support /dev/fd/n or your shell can't make use of named pipes for its process substitution, that's where you'd have to deal with named pipes by hand.

Related Question