2

I can exit a program on error like so

ls /fake/folder || exit 1

I can redirect the output to a file and STDOUT like so

ls /usr/bin | tee foo.txt

But I can't do

ls /fake/folder | tee foo.txt || exit 1

because I get the output of tee and not ls

How do I redirect the output to both a file and STDOUT and exit on error

puk
  • 16,318
  • 29
  • 119
  • 199

1 Answers1

6

This is exactly what the pipefail runtime option is meant for:

# Make a pipeline successful only if **all** components are successful
set -o pipefail
ls /fake/folder | tee foo.txt || exit 1

If you want to be explicit about precedence, by the way, consider:

set -o pipefail
{ ls /fake/folder | tee foo.txt; } || exit 1  # same thing, but maybe more clear

...or, if you want to avoid making runtime configuration changes, you can use PIPESTATUS to check the exit status of any individual element of the most recent pipeline:

ls /fake/folder | tee foo.txt
(( ${PIPESTATUS[0]} == 0 )) || exit

If you don't want to take any of the approaches above, but are willing to use ksh extensions adopted by bash, putting it in a process substitution rather than a pipeline will prevent tee from impacting exit status:

ls /fake/folder > >(tee foo.txt) || exit 1
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441