The following is probably just another case of these: ... On Tue, 2024-11-05 at 03:04 +0100, Christoph Anton Mitterer wrote: > $ $(foo) || true > a > $ $(foo) && true > a > > => these I don't understand > it's and AND-OR list, not the last element, so -e should be > ignored, > yet it kicks in at the false ... but I'm not 100% sure, so perhaps some expert can confirm. I had this function, which was checking whether some file contained some byte: is_file_containing_bytes() { local file="$1" local octal_bytes="$2" local number_of_matching_bytes='' local exit_status=0 number_of_matching_bytes="$( export LC_ALL=C exec 4>&1 exitstatus_command1="$( { { cat "${file}" 2>/dev/null 3>&- printf "$?" >&3 echo "DEBUG" >&2 } 4>&- | \ { tr -d -c "${octal_bytes}" | wc -c; } >&4 3>&- 4>&- } 3>&1 )" 4>&1 exec 4>&- if [ "${exitstatus_command1}" != '0' ]; then exit 1 fi )" || exit_status="$?" if [ "${exit_status}" -ne 0 ]; then return 2 fi if [ "${number_of_matching_bytes}" != '0' ]; then return 0 else return 1 fi } That was from back when there was no portable set -o pipefail and I wanted to also catch any error in cat (e.g. when file not found) and let through anything on stderr. Again, set -e in place, I do: is_file_containing_bytes non-existent '\000' The cat/printf are in a pipe but without a leading !, so when cat error because of the file not found, set -e should kick in and DEBUG not printed. The function works nevertheless, because 0 isn't captured in exitstatus_command1 either. However, back then I oversaw, that the whole thing is again behind a || and that in turn should again cause set -e to be ignored, so exitstatus_command1 should actually capture the 1 from cat (and the function properly fail because of that) and should also print the DEBUG, because set -e is ignored. But in dash, it doesn't. Probably it's the same case than above, but it felt a bit convoluted, because the pipe not ignoring the set -e but the outer AND-OR list should ignore it. Cheers, Chris.