On 20/11/15 02:20, Pádraig Brady wrote: > I'm coming around to making a change here. > > Either be quiet about: > datagen | tee >(sha1sum --tag) >(md5sum --tag) >&- | sort | gpg --clearsign > > Or support: > datagen | tee --no-stdout >(sha1sum --tag) >(md5sum --tag) | sort | gpg > --clearsign > > I like the idea of supporting this with no new option. > I see we have similar EBADF handling in touch and nohup. > I'll sleep on it.
The attached supports the >&- usage above. cheers, Pádraig.
>From bbd741b0eb290ff94b8f0f4bbe40d4fc7e9e5ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Fri, 20 Nov 2015 11:54:00 +0000 Subject: [PATCH] tee: don't diagnose a closed standard output This can be useful if you want data from process substitutions coalesced through stdout. For example: datagen | tee >(md5sum --tag) >(sha256sum --tag) >&- | sort * src/tee.c (tee_files): Don't diagnose EBADF on stdout. * tests/misc/tee.sh: Add a test case. * doc/coreutils.texi (tee invocation): Mention that -p is useful with pipes that may not consume all data. Add a closed stdout example, similar to the one above. * NEWS: Mention the change in behavior. * THANKS.in: Add the suggester, Jirka Hladky. --- NEWS | 3 +++ THANKS.in | 1 + doc/coreutils.texi | 16 ++++++++++++++++ src/tee.c | 8 +++++++- tests/misc/tee.sh | 7 +++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index fc5e927..5fe0ea2 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,9 @@ GNU coreutils NEWS -*- outline -*- ls now quotes file names unambiguously and appropriate for use in a shell, when outputting to a terminal. + tee no longer diagnoses write errors to a closed standard output, as this + can be useful when further piping the output from process substitutions. + ** Improvements All utilities now quote user supplied arguments in error strings, diff --git a/THANKS.in b/THANKS.in index 51c77ef..5c49006 100644 --- a/THANKS.in +++ b/THANKS.in @@ -299,6 +299,7 @@ Jesse Thilo j...@eecs.lehigh.edu Jie Xu x...@iag.net Jim Blandy j...@cyclic.com Jim Dennis j...@starshine.org +Jirka Hladky jhla...@redhat.com Joakim Rosqvist dvl...@cs.umu.se Jochen Hein joc...@jochen.org Joe Orton j...@manyfish.co.uk diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 8034807..1755a51 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -13019,6 +13019,11 @@ so it works with @command{zsh}, @command{bash}, and @command{ksh}, but not with @command{/bin/sh}. So if you write code like this in a shell script, be sure to start the script with @samp{#!/bin/bash}. +Note also that if any of the process substitutions (or piped stdout) +might exit early without consuming all the data, the @option{-p} option +is needed to allow @command{tee} to continue to process the input +to any remaining outputs. + Since the above example writes to one file and one process, a more conventional and portable use of @command{tee} is even better: @@ -13087,6 +13092,17 @@ tar chof - "$tardir" \ | bzip2 -9 -c > your-pkg-M.N.tar.bz2 @end example +If you want to further process the output from process substitutions, +and those outputs are smaller than the system's PIPE_BUF size, resulting +in atomic writes, it's useful to close stdout like: + +@example +tardir=your-pkg-M.N +tar chof - "$tardir" \ + | tee >(md5sum --tag) >(sha256sum --tag) >&- \ + | sort | gpg --clearsign > your-pkg-M.N.tar.sig +@end example + @exitstatus diff --git a/src/tee.c b/src/tee.c index ae1bb30..9ef7742 100644 --- a/src/tee.c +++ b/src/tee.c @@ -246,7 +246,13 @@ tee_files (int nfiles, char **files) bool fail = errno != EPIPE || (output_error == output_error_exit || output_error == output_error_warn); if (descriptors[i] == stdout) - clearerr (stdout); /* Avoid redundant close_stdout diagnostic. */ + { + /* Don't diagnose a closed stdout. */ + if (errno == EBADF) + fail = false; + /* Avoid redundant close_stdout diagnostic. */ + clearerr (stdout); + } if (fail) { error (output_error == output_error_exit diff --git a/tests/misc/tee.sh b/tests/misc/tee.sh index f457a0b..bc51c9a 100755 --- a/tests/misc/tee.sh +++ b/tests/misc/tee.sh @@ -63,6 +63,13 @@ if test -w /dev/full && test -c /dev/full; then test $(wc -l < err) = 1 || { cat err; fail=1; } fi +# Ensure tee doesn't diagnose a closed stdout +# which can be useful when coalescing small atomic outputs +# from process substitutions like: +# $ seq 100000 | tee -p >(head -n10 | wc -l) >(wc -l) >&- | cat +# 10 +# 100000 +echo | tee >&- || fail=1 # Ensure tee honors --output-error modes mkfifo_or_skip_ fifo -- 2.5.0