#!/bin/sh set -eu usage() { cat <<-'EOF' Usage: muffle [-n] [--] COMMAND... muffle -h EOF } help() { cat <<-'EOF' Options: -n invert when to do the muffling -h, --help show this message COMMAND the COMMAND to be muffled Conditionally omit STDOUT and STDERR of COMMAND: if command exits with an error, print its original output to the corresponding streams, but when there is no error, throw the output away, "muffling" the COMMAND. Examples: Only print anything if the test fails: $ muffle sh tests/assert-makefile.sh EOF } for flag in "$@"; do case "$flag" in (--) break ;; (--help) usage help exit ;; (*) ;; esac done INVERT=false while getopts 'nh' flag; do case "$flag" in (n) INVERT=true ;; (h) usage help exit ;; (*) usage >&2 exit 2 ;; esac done shift $((OPTIND - 1)) OUT="$(mkstemp)" ERR="$(mkstemp)" STATUS_F="$(mkstemp)" trap 'rm -f "$OUT" "$ERR" "$STATUS_F"' EXIT timed() { ts -s -m '%.s' } echo 0 > "$STATUS_F" { { "$@" || echo $? > "$STATUS_F"; } | timed | pre out > "$OUT" } 2>&1 | timed | pre err > "$ERR" STATUS="$(cat "$STATUS_F")" if [ "$INVERT" = false -a "$STATUS" != 0 ] || [ "$INVERT" = true -a "$STATUS" = 0 ]; then cat "$OUT" "$ERR" | sort -k2 | while read -r line; do if [ "$(printf '%s\n' "$line" | cut -d' ' -f1)" = 'out:' ]; then printf '%s\n' "$line" | cut -d' ' -f3- >&1 else printf '%s\n' "$line" | cut -d' ' -f3- >&2 fi done exit "$STATUS" fi