diff --git a/SC2015.md b/SC2015.md new file mode 100644 index 0000000..6b9acdb --- /dev/null +++ b/SC2015.md @@ -0,0 +1,29 @@ +# Note that A && B || C is not if-then-else. C may run when A is true. + +### Problematic code: + + [[ $dryrun ]] && echo "Would delete file" || rm file + +### Correct code: + + if [[ $dryrun ]] + then + echo "Would delete file" + else + rm file + fi + +### Rationale: + +It's common to use `A && B` to run `B` when `A` is true, and `A || C` to run `C` is `A` is false. + +However, combining them into `A && B || C` is not the same as `if A then B else C`. + +In this case, if `A` is true but `B` is false, `C` will run. + +For the code sample above, if the script was run with stdout closed for any reason (such as explicitly running `script --dryrun >&-`), echo would fail and return false and the file would be deleted, even though `$dryrun` was set! + +If an `if` clause is used instead, this problem is avoided. + +### Contraindications +Ignore this warning when you actually do intend to run C when either A or B fails. \ No newline at end of file