According to this, placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created.Using ps to see this in actionThis is the process hierarchy for a process pipeline executed directly on command line. 4398 is the PID for the login shell:sleep 2 | ps -H;  PID TTY          TIME CMD   4398 pts/23   00:00:00 bash   29696 pts/23   00:00:00   sleep   29697 pts/23   00:00:00   psNow follows the process hierarchy for a process pipeline between curly braces executed directly on command line. 4398 is the PID for the login shell. It's similar to the hierarchy above proving that everything is executed in current shell context:{ sleep 2 | ps -H; }   PID TTY          TIME CMD    4398 pts/23   00:00:00 bash    29588 pts/23   00:00:00   sleep    29589 pts/23   00:00:00   psNow, this is the process hierarchy when the sleep in the pipeline is itself placed inside curly braces (so two levels of braces in all){ { sleep 2; } | ps -H; }  PID TTY          TIME CMD   4398 pts/23   00:00:00 bash   29869 pts/23   00:00:00   bash   29871 pts/23   00:00:00     sleep   29870 pts/23   00:00:00   psWhy does bash have to create a subshell to run sleep in the 3rd case when the documentation states that commands between curly braces are executed in current shell context?
Bash subshell creation with curly braces
bash;subshell
In a pipeline, all commands run concurrently (with their stdout/stdin connected by pipes) so in different processes.Incmd1 | cmd2 | cmd3All three commands run in different processes, so at least two of them have to run in a subshell. Some shells run one of them in the current shell process (if builtin like read or if the pipeline is the last command of the script), but bash runs them all in their own separate process (except with the lastpipe option in recent bash versions and under some specific conditions).{...} groups commands. If that group is part of a pipeline, it has to run in a separate process just like a simple command.In:{ a; b $?; } | cWe need a shell to evaluate that a; b $? is a separate process, so we need a subshell. The shell could optimise by not forking for b since it's the last command to be run in that group. Some shells do it, but apparently not bash.