[PATCH 2/6] Capture test output via out-to err-to both-to instead of eval/tee

0 views
Skip to first unread message

Rob Browning

unread,
Apr 16, 2026, 8:02:37 PMApr 16
to bup-...@googlegroups.com
The

WVPASS eval 'cmd ... 2> >(tee log)'
WVPASS grep ... log

approach to capture and examine cmd's stderr is racy because it
doesn't wait for the tee to finish. We can, and have in some recent
cases like

61dff81a99eac59d00f5ce1a26e6e1d1ee11c8dd
get: improve symlink repairs and add tests

avoided the race via an extra fifo like so:

WVPASS mkfifo done
...
WVPASS eval 'cmd ... 2> >(tee log; : > done)'
WFVAIL read done
WVPASS grep ... log

Instead of distributing that approach everywhere, add new btl.sh
out-to, err-to, and both-to commands that can handle the same task
like this:

WVPASS err-to log cmd ...
WVPASS grep ... log

which is simpler, both in appearance and internally, since it just
uses some extra plumbing (file descriptors) to do the same job.

Replace all the existing eval/tee/fifo uses with equivalent *-to
invocations.

Signed-off-by: Rob Browning <r...@defaultvalue.org>
Tested-by: Rob Browning <r...@defaultvalue.org>
---

Pushed to main.

test/ext/test-btl | 44 +++++++++++++++++++++++
test/ext/test-cat-file | 15 ++++----
test/ext/test-get-excludes | 5 +--
test/ext/test-get-missing | 11 +++---
test/ext/test-get-repair-bupm | 12 +++----
test/ext/test-get-repair-symlinks | 19 ++++------
test/ext/test-get-rewrite-missing | 59 ++++++++++++-------------------
test/ext/test-rm | 2 +-
test/ext/test-tag | 6 ++--
test/ext/test-validate-ref-links | 17 +++++----
test/ext/test-validate-refs | 4 +--
test/lib/btl.sh | 44 +++++++++++++++++++++++
12 files changed, 151 insertions(+), 87 deletions(-)
create mode 100755 test/ext/test-btl

diff --git a/test/ext/test-btl b/test/ext/test-btl
new file mode 100755
index 00000000..fb84d2d5
--- /dev/null
+++ b/test/ext/test-btl
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+. ./wvtest-bup.sh || exit $?
+. ./test/lib/btl.sh || exit $?
+
+set -o pipefail
+
+top="$(WVPASS pwd)" || exit $?
+tmpdir="$(WVPASS wvmktempdir)" || exit $?
+
+out-err() { echo out; echo err 1>&2; }
+
+WVPASS cd "$tmpdir"
+
+
+WVSTART '{err,out,both,}-to redirection'
+
+WVPASS rm -f log
+WVPASS err-to log out-err
+WVPASSEQ err "$(< log)"
+
+WVPASS rm -f log
+WVPASS out-to log out-err
+WVPASSEQ out "$(< log)"
+
+WVPASS rm -f out err
+WVPASS both-to out err out-err
+WVPASSEQ out "$(< out)"
+WVPASSEQ err "$(< err)"
+
+
+WVSTART '{err,out,both}-to exit status preservation'
+WVPASS out-to log true
+WVFAIL out-to log false
+WVEXPRC 42 out-to log sh -c 'exit 42'
+WVPASS err-to log true
+WVFAIL err-to log false
+WVEXPRC 42 err-to log sh -c 'exit 42'
+WVPASS both-to out err true
+WVFAIL both-to out err false
+WVEXPRC 42 both-to out err sh -c 'exit 42'
+
+
+WVPASS cd "$top"
+WVPASS rm -rf "$tmpdir"
diff --git a/test/ext/test-cat-file b/test/ext/test-cat-file
index 1fa344dc..34a692b7 100755
--- a/test/ext/test-cat-file
+++ b/test/ext/test-cat-file
@@ -1,5 +1,6 @@
#!/usr/bin/env bash
. ./wvtest-bup.sh || exit $?
+. test/lib/btl.sh || exit $?

set -o pipefail

@@ -21,19 +22,19 @@ WVPASS bup index src
WVPASS bup save -n src --strip-path "$(pwd)" src

WVSTART 'invalid invocations'
-WVFAIL eval 'bup cat-file 2> >(tee log)'
+WVFAIL err-to log bup cat-file
WVPASS grep -F 'must specify a target' log
-WVFAIL eval 'bup cat-file x y 2> >(tee log)'
+WVFAIL err-to log bup cat-file x y
WVPASS grep -F 'only one target file allowed' log
-WVFAIL eval 'bup cat-file --meta --bupm x 2> >(tee log)'
+WVFAIL err-to log bup cat-file --meta --bupm x
WVPASS grep -F -e '--meta and --bupm are incompatible' log
-WVFAIL eval 'bup cat-file x 2> >(tee log)'
+WVFAIL err-to log bup cat-file x
WVPASS grep -F -e "path x doesn't include a branch and revision" log
-WVEXPRC 2 eval 'bup cat-file x/y 2> >(tee log)'
+WVEXPRC 2 err-to log bup cat-file x/y
WVPASS grep -F 'cannot access /x in x/y' log
-WVFAIL eval 'bup cat-file --bupm src/latest/src/foo 2> >(tee log)'
+WVFAIL err-to log bup cat-file --bupm src/latest/src/foo
WVPASS grep -F 'src/latest/src/foo is not a directory' log
-WVFAIL eval 'bup cat-file src/latest/src/ 2> >(tee log)'
+WVFAIL err-to log bup cat-file src/latest/src/
WVPASS grep -F 'src/latest/src/ is not a plain file' log

WVPASS bup cat-file "src/latest/src/foo" > cat-foo
diff --git a/test/ext/test-get-excludes b/test/ext/test-get-excludes
index c21b5600..3160e5c5 100755
--- a/test/ext/test-get-excludes
+++ b/test/ext/test-get-excludes
@@ -13,7 +13,6 @@ export GIT_DIR="$tmpdir/bup"
bup() { "$top/bup" "$@"; }

WVPASS cd "$tmpdir"
-WVPASS mkfifo done
WVPASS bup init

WVPASS mkdir -p src/a
@@ -41,9 +40,7 @@ WVPASSEQ $'one\nthree\ntwo' "$(bup ls dst-2/latest/a)"
WVPASSEQ $'three\ntwo' "$(bup ls dst-3/latest/a)"

WVSTART 'ignored contextual arguments are disallowed'
-WVEXPRC 2 eval 'bup get --rewrite --append x --exclude-rx y --ignore-missing' \
- '2> >(tee err.log; : > done)'
-WVFAIL read < done
+WVEXPRC 2 err-to err.log bup get --rewrite --append x --exclude-rx y --ignore-missing
WVPASS grep -E '^error: trailing arguments with no effect: --exclude-rx --ignore-missing' err.log

WVPASS cd "$top"
diff --git a/test/ext/test-get-missing b/test/ext/test-get-missing
index e89aa0b2..0290d73c 100755
--- a/test/ext/test-get-missing
+++ b/test/ext/test-get-missing
@@ -54,18 +54,17 @@ WVPASS rm -rf dest-repo

WVSTART 'get incomplete tree with --ignore-missing'
WVPASS bup -d dest-repo init
-WVEXPRC 2 eval 'bup -d dest-repo get -s bup --ignore-missing ' \
- '--unnamed "git:$a_oid" 2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup -d dest-repo get -s bup --ignore-missing \
+ --unnamed "git:$a_oid"
WVPASSEQ 1 "$(grep -cF "skipping missing source object ${bupm_oid}" get.log)"
WVPASS rm -rf dest-repo


WVSTART 'multiple incomplete tree gets with differing ignores'
WVPASS bup -d dest-repo init
-WVEXPRC 2 eval 'bup -d dest-repo get -s bup' \
- ' --ignore-missing --unnamed "git:$a_oid"'\
- ' --no-ignore-missing --unnamed "git:$b_oid"'\
- ' 2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup -d dest-repo get -s bup \
+ --ignore-missing --unnamed "git:$a_oid" \
+ --no-ignore-missing --unnamed "git:$b_oid"
WVPASSEQ 1 "$(grep -cF "skipping missing source object ${bupm_oid}" get.log)"
log_msg_line="$(WVPASS grep -nF "skipping missing source object ${bupm_oid}" get.log)"
log_msg_line="${log_msg_line%%:*}"
diff --git a/test/ext/test-get-repair-bupm b/test/ext/test-get-repair-bupm
index 5eeeb125..ccbec567 100755
--- a/test/ext/test-get-repair-bupm
+++ b/test/ext/test-get-repair-bupm
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-. ./wvtest-bup.sh
-. ./test/lib/btl.sh
+. ./wvtest-bup.sh || exit $?
+. ./test/lib/btl.sh || exit $?

set -o pipefail

@@ -58,20 +58,18 @@ save_date="${saves[2]}"
unset saves

# May as well double-check, though test-validate-refs already does this
-WVEXPRC 1 eval 'bup validate-refs --bupm 2>&1 | tee validate.log'
+WVEXPRC 1 err-to validate.log bup validate-refs --bupm
btl-display-file validate.log
wv-match-rx "$(< validate.log)" \
"abridged-bupm refs/heads/src $broken_tree_oid:\.bupm/?"

# Ensure a normal rewrite rejects the abridged bupm
-WVEXPRC 2 eval 'bup get --rewrite --append: src dst 2>&1 | tee rewrite.log'
-btl-display-file rewrite.log
+WVEXPRC 2 bup get --rewrite --append: src dst

WVPASS umask 077

# Test repair
-WVEXPRC 3 eval 'bup get --repair --append: src dst 2>&1 | tee rewrite.log'
-btl-display-file rewrite.log
+WVEXPRC 3 err-to rewrite.log bup get --repair --append: src dst
set-repair-id rewrite.log

# Check commit message trailers
diff --git a/test/ext/test-get-repair-symlinks b/test/ext/test-get-repair-symlinks
index 6f6de35b..7087f036 100755
--- a/test/ext/test-get-repair-symlinks
+++ b/test/ext/test-get-repair-symlinks
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-. ./wvtest-bup.sh
-. ./test/lib/btl.sh
+. ./wvtest-bup.sh || exit $?
+. ./test/lib/btl.sh || exit $?

set -o pipefail

@@ -14,7 +14,6 @@ bup() { "$top/bup" "$@"; }


WVPASS cd "$tmpdir"
-WVPASS mkfifo done
WVPASS bup init


@@ -34,8 +33,7 @@ WVEXPRC 2 bup join src: > /dev/null

WVSTART 'symlinks with metadata but no blob are noticed'
WVPASS bup init dst
-WVEXPRC 2 eval 'bup -d dst get -s bup --append src 2> >(tee err.log; : > done)'
-WVFAIL read < done
+WVEXPRC 2 err-to err.log bup -d dst get -s bup --append src
WVPASS grep -E "object .*${two_oid}.* is missing" err.log
WVPASS rm -rf dst

@@ -63,9 +61,7 @@ WVPASS git branch -f src "$not_1_save"

WVSTART "symlinks with mismatched targets are noticed by --rewrite"
WVPASS bup init dst
-WVEXPRC 2 eval 'bup -d dst get -s bup --rewrite --pick src/latest' \
- '2> >(tee err.log; : > done)'
-WVFAIL read < done
+WVEXPRC 2 err-to err.log bup -d dst get -s bup --rewrite --pick src/latest
WVPASS grep -qF "Symlink with mismatched targets (can --repair)" err.log
WVPASS rm -rf dst

@@ -95,12 +91,9 @@ WVEXPRC 2 bup join src: > /dev/null

WVSTART 'symlinks completely missing are noticed by --copy/--rewrite'
WVPASS bup init dst
-WVEXPRC 2 eval 'bup -d dst get -s bup --append src 2> err.log'
-btl-display-file err.log
+WVEXPRC 2 err-to err.log bup -d dst get -s bup --append src
WVPASS grep -E "object .*${two_oid}.* is missing" err.log
-WVEXPRC 2 eval 'bup -d dst get -s bup --rewrite --append src' \
- '2> >(tee err.log; : > done)'
-WVFAIL read < done
+WVEXPRC 2 err-to err.log bup -d dst get -s bup --rewrite --append src
WVPASS grep -E "object .*${two_oid}.* is missing" err.log
WVPASS rm -rf dst

diff --git a/test/ext/test-get-rewrite-missing b/test/ext/test-get-rewrite-missing
index 009c681d..88e444d9 100755
--- a/test/ext/test-get-rewrite-missing
+++ b/test/ext/test-get-rewrite-missing
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-. ./wvtest-bup.sh
-. ./test/lib/btl.sh
+. ./wvtest-bup.sh || exit $?
+. ./test/lib/btl.sh || exit $?

set -o pipefail

@@ -18,7 +18,6 @@ bup() { "$top/bup" "$@"; }
# Missing symlinks are tested in test-get-repair-symlinks

WVPASS cd "$tmpdir"
-WVPASS mkfifo done
WVPASS bup init
WVPASS git config bup.split.trees true

@@ -121,16 +120,13 @@ WVPASS cp -pPR bup bup-tmp

WVFAIL bup get --no-ignore-missing --rewrite --append src

-WVFAIL eval 'bup get --ignore-missing --rewrite --append src 2> >(tee get.log; : > done)'
-WVFAIL read < done
+WVFAIL err-to get.log bup get --ignore-missing --rewrite --append src
WVPASS grep -E '^error: --ignore-missing and --rewrite are incompatible' get.log

-WVFAIL eval 'bup get --ignore-missing --repair --append src 2> >(tee get.log; : > done)'
-WVFAIL read < done
+WVFAIL err-to get.log bup get --ignore-missing --repair --append src
WVPASS grep -E '^error: --ignore-missing and --repair are incompatible' get.log

-WVFAIL eval 'bup get --ignore-missing --append src 2> >(tee get.log; : > done)'
-WVFAIL read < done
+WVFAIL err-to get.log bup get --ignore-missing --append src
WVPASS grep -E '^error: currently only --unnamed allows --ignore-missing' get.log

repair-to-dest()
@@ -138,9 +134,7 @@ repair-to-dest()
rm -rf dest-repo
WVPASS bup -d dest-repo init
WVPASS git --git-dir dest-repo config bup.split.trees true
- WVEXPRC 3 eval 'bup -d dest-repo get -s bup --repair --append src' \
- '2> >(tee repair.log; : > done)'
- WVFAIL read < done
+ WVEXPRC 3 err-to repair.log bup -d dest-repo get -s bup --repair --append src
}

set-repair-id()
@@ -310,50 +304,44 @@ WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
# Check that non-rewrite doesn't notice the missing object (b/c same repo)
WVEXPRC 3 bup get --repair --append: src r1 --copy --append: src r2
# Then that a second *rewrite* can't handle the missing file
-WVEXPRC 2 eval 'bup get' \
- '--repair --append: src r1' \
- '--rewrite --append: src r2' \
- '2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup get \
+ --repair --append: src r1 \
+ --rewrite --append: src r2
WVPASS grep -E 'raise MissingObject' get.log


WVSTART '--ignore-missing on broken save after --repair'
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
WVPASS bup init bup-dest
-WVEXPRC 2 eval 'bup -d bup-dest get -s bup' \
- '--repair --append: src r1' \
- '--copy --unnamed src' \
- '2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup -d bup-dest get -s bup \
+ --repair --append: src r1 \
+ --copy --unnamed src
WVPASS grep -E 'raise MissingObject' get.log
-WVEXPRC 2 eval 'bup -d bup-dest get -s bup' \
- '--repair --append: src r1' \
- '--copy --ignore-missing --unnamed src' \
- ' 2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup -d bup-dest get -s bup \
+ --repair --append: src r1 \
+ --copy --ignore-missing --unnamed src
WVPASS grep -E '^skipping missing source object' get.log


WVSTART '--copy --rewrite --repair'
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
-WVEXPRC 3 eval 'bup get --rewrite --repair --repair-id r1 --append: src r1' \
- '2>&1 | tee get.log'
+WVEXPRC 3 err-to get.log bup get --rewrite --repair --repair-id r1 --append: src r1
WVPASSEQ 1 "$(git show r1:a/2 | grep -cE '^Bup-Replacement-Info: r1$')"
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
-WVEXPRC 2 eval 'bup get --repair --rewrite --append: src r1 2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup get --repair --rewrite --append: src r1
WVPASS grep -E 'raise MissingObject' get.log
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
WVPASS rm -rf bup-dest && bup init bup-dest
-WVEXPRC 2 eval 'bup -d bup-dest get -s bup --repair --copy --append: src r1' \
- '2>&1 | tee get.log'
+WVEXPRC 2 err-to get.log bup -d bup-dest get -s bup --repair --copy --append: src r1
WVPASS grep -E 'raise MissingObject' get.log
WVPASS rm -rf bup bup-dest


WVSTART 'multiple gets with differing repair-ids'
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
-WVEXPRC 3 eval 'bup get --repair' \
- '--repair-id repair-1 --append: src r1' \
- '--repair-id repair-2 --append: src r2' \
- '2>&1 | tee get.log'
+WVEXPRC 3 err-to get.log bup get --repair \
+ --repair-id repair-1 --append: src r1 \
+ --repair-id repair-2 --append: src r2
# Check commit messages
bup_ver="$(bup version)"
WVPASS git show -s --pretty=email r1 | tee repair-msg
@@ -397,9 +385,8 @@ WVPASSEQ 1 "$(WVPASS grep -cE '^Bup-Replacement-Info: repair-2$' replacement-2)"

WVSTART "trailers don't accumulate across repaired saves"
WVPASS rm -rf bup && WVPASS cp -pPR bup-1234 bup
-WVEXPRC 3 eval 'bup get --repair' \
- '--repair-id repair-id --append: src-two-saves r1' \
- '2>&1 | tee get.log'
+WVEXPRC 3 err-to get.log bup get --repair \
+ --repair-id repair-id --append: src-two-saves r1
WVPASS git show -s --pretty=email r1^ | tee repair-msg-1
WVPASS git show -s --pretty=email r1 | tee repair-msg-2
WVPASS git interpret-trailers --parse < repair-msg-1 | tee repair-trailers-1
diff --git a/test/ext/test-rm b/test/ext/test-rm
index fcae8ed6..5073f071 100755
--- a/test/ext/test-rm
+++ b/test/ext/test-rm
@@ -18,7 +18,7 @@ WVPASS bup init
WVPASS cd "$tmpdir"


-WVFAIL eval 'bup rm --unsafe 2> >(tee log)'
+WVFAIL err-to log bup rm --unsafe
WVPASS grep -F 'no paths specified' log


diff --git a/test/ext/test-tag b/test/ext/test-tag
index 12dbc1a4..fa8907bf 100755
--- a/test/ext/test-tag
+++ b/test/ext/test-tag
@@ -18,7 +18,7 @@ WVPASS cd "$tmpdir"
WVPASS bup index "$top/test/sampledata"
WVPASS bup save -n main "$top/test/sampledata"
WVPASSEQ "$(git tag)" ''
-WVFAIL eval 'bup tag -d nope 2> >(tee log)'
+WVFAIL err-to log bup tag -d nope
WVPASS grep "error: tag 'nope' doesn't exist" log
WVPASSEQ "$(git tag)" ''
WVPASS bup tag -f -d nope
@@ -27,10 +27,10 @@ WVFAIL bup tag tag-1
WVPASSEQ "$(git tag)" ''
WVFAIL bup tag '' nope
WVPASSEQ "$(git tag)" ''
-WVFAIL eval 'bup tag tag-1 nope 2> >(tee log)'
+WVFAIL err-to log bup tag tag-1 nope
WVPASS grep "error: commit nope not found" log
WVPASSEQ "$(git tag)" ''
-WVFAIL eval 'bup tag .tag-1 main 2> >(tee log)'
+WVFAIL err-to log bup tag .tag-1 main
WVPASS grep "'.tag-1' is not a valid tag name" log
WVPASSEQ "$(git tag)" ''
WVPASS bup tag tag-1 main
diff --git a/test/ext/test-validate-ref-links b/test/ext/test-validate-ref-links
index efdd7d9a..761d4a40 100755
--- a/test/ext/test-validate-ref-links
+++ b/test/ext/test-validate-ref-links
@@ -19,7 +19,7 @@ expect-one-src-missing()
else
args="$(printf " %q" "$@")"
fi
- WVEXPRC 1 eval "bup validate-ref-links $args > validate.log 2>&1"
+ WVEXPRC 1 err-to validate.log bup validate-ref-links $args
btl-display-file validate.log
WVPASSEQ 1 "$(grep -cE '^missing ' validate.log)"
}
@@ -34,8 +34,9 @@ WVPASS echo 3 > src/a/3
WVPASS bup index src
WVPASS bup save --strip -n src src

-WVPASS bup validate-ref-links 2>&1 | tee validate.log
-WVPASS grep -vE '^missing ' validate.log
+WVPASS both-to out err bup validate-ref-links
+WVPASSEQ 0 "$(grep -cE '^missing ' out)"
+WVPASSEQ 0 "$(grep -cE '^missing ' err)"

bupm_oid="$(WVPIPE git ls-tree src:a | WVPASS head -1 | WVPASS btl-ent-oid)" \
|| exit $?
@@ -52,15 +53,17 @@ WVPASS echo 5 > more/a/5
WVPASS bup index more
WVPASS bup save --strip -n more more

-WVPASS bup validate-ref-links more 2>&1 | tee validate.log
-WVPASS grep -vE '^missing ' validate.log
+WVPASS both-to out err bup validate-ref-links more
+WVPASSEQ 0 "$(grep -cE '^missing ' out)"
+WVPASSEQ 0 "$(grep -cE '^missing ' err)"

expect-one-src-missing
expect-one-src-missing src

WVPASS bup rm --unsafe src
-WVPASS bup validate-ref-links 2>&1 | tee validate.log
-WVPASS grep -vE '^missing ' validate.log
+WVPASS both-to out err bup validate-ref-links
+WVPASSEQ 0 "$(grep -cE '^missing ' out)"
+WVPASSEQ 0 "$(grep -cE '^missing ' err)"


WVPASS cd "$top"
diff --git a/test/ext/test-validate-refs b/test/ext/test-validate-refs
index 82425cf4..897b76a1 100755
--- a/test/ext/test-validate-refs
+++ b/test/ext/test-validate-refs
@@ -65,10 +65,8 @@ broken_save=$(WVPASS git commit-tree "$broken_tree_oid" -p src -m 'abridged bupm
WVPASS git branch -f src "$broken_save"
WVPASS bup validate-refs --links 2>&1 | tee validate.log
WVPASS grep -vE '^missing ' validate.log
-WVPASS mkfifo done
for args in --bupm ''; do
- WVEXPRC 1 eval 'bup validate-refs $args 2> >(tee validate.log; : > done)'
- WVFAIL read < done
+ WVEXPRC 1 err-to validate.log bup validate-refs $args
WVPASSEQ 1 "$(grep -cE "abridged-bupm refs/heads/src [0-9a-f]{40}:\.bupm" validate.log)"
done

diff --git a/test/lib/btl.sh b/test/lib/btl.sh
index 255c84db..f2afd2b9 100644
--- a/test/lib/btl.sh
+++ b/test/lib/btl.sh
@@ -24,3 +24,47 @@ btl-display-file()
cat "$name" || exit $?
printf -- "----- \"%q\" content above -----\n" "$name" || exit $?
}
+
+
+# out-to, err-to, and both-to allow redirections of just stdout or
+# stderr when using "wrapper" commands like WVPASS, WVFAIL, ... For
+# example
+#
+# WVPASS err-to err.log some --random --comand
+# WVPASS grep ... err.log
+#
+# This avoids capturing the WV command's output in the log which
+# happens for something like "WVPASS ... > err.log". This also makes
+# sure the comand doesn't return until the output is finished, which
+# isn't the case for a process substitution like this:
+#
+# WVPASS eval "some --command 2> >(tee err.log)"
+#
+
+out-to()
+{
+ test $# -gt 1 || { echo 'Usage: out-to OUT cmd ...' 1>&2; exit 2; }
+ local out="$1"
+ shift
+ "$@" | tee "$out"
+ return "${PIPESTATUS[0]}"
+}
+
+err-to()
+{
+ test $# -gt 1 || { echo 'Usage: err-to ERR cmd ...' 1>&2; exit 2; }
+ local err="$1" fd rc
+ shift
+ { "$@" 2>&1 >&${fd} {fd}>&- | tee "$err" {fd}>&-; rc="${PIPESTATUS[0]}"; } \
+ {fd}>&1
+ : {fd}>&-
+ return $rc
+}
+
+both-to()
+{
+ test $# -gt 2 || { echo 'Usage: both-to OUT ERR cmd ...' 1>&2; exit 2; }
+ local out="$1" err="$2"
+ shift 2
+ err-to "$err" out-to "$out" "$@"
+}
--
2.47.3

Reply all
Reply to author
Forward
0 new messages