Created SC2031 (markdown)

koalaman
2014-02-27 11:24:20 -08:00
parent ce0a17cedb
commit a28ff2e6e0

60
SC2031.md Normal file

@@ -0,0 +1,60 @@
# var was modified in a subshell. That change might be lost.
### Problematic code:
There are many ways of accidentally creating subshells, but a common one is piping to a loop:
n=0
printf "%s\n" {1..10} | while read i; do (( n+=i )); done
echo $n
### Correct code:
# Bash specific:
n=0
while read i; do (( n+=i )); done < <(printf "%s\n" {1..10})
echo $n
In `sh`, a temp file can be used instead of process substitution.
### Rationale:
Variables set in subshells are not available outside the subshell. This is a wide topic, and better described on the [Wooledge Bash Wiki](http://mywiki.wooledge.org/BashFAQ/024).
Here are some constructs that cause subshells (shellcheck may not warn about all of them). In each case, you can replace `subshell1` by a command or function that sets a variable, e.g. simply `var=foo`, and the variable will appear to be unset after the command is run. Similarly, you can replace `regular` with `var=foo`, and it will be set afterwards:
Pipelines:
subshell1 | subshell2 | subshell3 # Bash, Dash, Ash
subshell1 | subshell2 | regular # Ksh, Zsh
Command substitution:
regular "$(subshell1)" "`subshell2`"
Process substitution:
regular <(subshell1) >(subshell2)
Some forms of grouping:
( subshell )
{ regular; }
Backgrounding:
subshell1 &
subshell2 &
Anything executed by external processes:
find . -exec subshell1 {} \;
find . -print0 | xargs -0 subshell2
sudo subshell3
su -c subshell4
This applies not only to setting variables, but also setting shell options and changing directories.
### Contraindications
You can ignore this error if you don't care that the changes aren't reflected, because work on the value branches and shouldn't be recombined.