From 1891a5bc86553f816c62ef7517b757bc5ffb7366 Mon Sep 17 00:00:00 2001 From: CH-DanReif <35710107+CH-DanReif@users.noreply.github.com> Date: Thu, 19 Apr 2018 14:48:44 -0700 Subject: [PATCH] Created SC2106 (markdown) --- SC2106.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 SC2106.md diff --git a/SC2106.md b/SC2106.md new file mode 100644 index 0000000..b00b314 --- /dev/null +++ b/SC2106.md @@ -0,0 +1,53 @@ +## SC2106: This only exits the subshell caused by the pipeline. + +### Problematic code: + +```sh +for i in a b c; do + echo hi | grep -q bye | break +done +``` + +### Correct code: + +```sh +for i in a b c; do + echo hi | grep -q bye || break +done +``` +### Rationale: + +The most common cause of this issue is probably using a single `|` when `||` was intended. The reason this message appears, though, is that a construction like this, intended to surface a failure inside of a loop: + +```sh +for i in a b c; do false | break; done; echo ${PIPESTATUS[@]} +``` + +may appear to work: +``` +$ for i in a b c; do false | break; done; echo ${PIPESTATUS[@]} +1 0 +``` + +What's actually happening, though, becomes clear if we add some `echo`s; the entire loop completes, and the `break` has no effect. + +```sh +$ for i in a b c; do echo $i; false | break; done; echo ${PIPESTATUS[@]} +a +b +c +1 0 +$ for i in a b c; do false | break; echo $i; done; echo ${PIPESTATUS[@]} +a +b +c +0 +``` + +Because bash processes pipelines by creating subshells, control statements like `break` only take effect in the subshell. + +### Related resources: + +* Contrast with the related, but different, problem in [this link](https://unix.stackexchange.com/questions/166546/bash-cannot-break-out-of-piped-while-read-loop-process-substitution-works). +* [Bash Reference Manual: Pipelines](https://www.gnu.org/software/bash/manual/bash.html#Pipelines), esp.: + > Each command in a pipeline is executed in its own subshell. \ No newline at end of file