There are several available options. One is to simply ditch cat
, and thus have no pipeline (which has the advantageous side effect of avoiding subshell use, and thus allowing changes to shell state -- variables set, etc -- to last beyond the inner loop):
set -e
for f; do # in "$@" is implicit
while read -r -a arr; do
printf 'Got line: '
printf '%q ' "${arr[@]}"
printf '\n'
done <"$f"
done
The above also goes out of its way to print the content read in a way that entirely preserves the array read, and prints its contents unambiguously (distinguishing an array containing two elements foo
bar baz
from one containing three elements foo
bar
baz
).
Another is to set pipefail
, which will cause a pipeline to be considered failed if any component of a pipeline returns a nonzero exit status, including cat
:
set -e
set -o pipefail
cat "$@" | while IFS= read -r; do
printf 'Got line: %q\n' "$REPLY"
done
This works by overriding the default behavior by which only the right-hand side of a pipeline matters for purposes of considering the overall exit status of the command.