Sample Header Ad - 728x90

Is the behavior of bash -c "<single command>" documented?

16 votes
1 answer
1290 views
It's quite known that when running bash -c "COMMAND" (at least in the common versions in Linux) when there's a single command without any [metacharacter](https://www.gnu.org/software/bash/manual/bash.html#index-metacharacter) (except for _space_, _tab_ or _newline_), the bash -c process will not fork, but rather replace itself by executing COMMAND directly with execve system call for optimization, so the result will only be one process.
-shellsession
$ pid=$$; bash -c "pstree -p $pid"
bash(5285)───pstree(14314)
If there's any metacharacter (such as redirection) or more than one command (which requires a metacharacter anyway), bash will fork for every command it executes.
-shellsession
$ pid=$$; bash -c ":; pstree -p $pid"
bash(5285)───bash(28769)───pstree(28770)

$ pid=$$; bash -c "pstree -p $pid 2>/dev/null"
bash(5285)───bash(14403)───pstree(14404)
Is this an undocumented optimization feature (which means it's not guaranteed), or is it documented somewhere and guaranteed? --- _Note:_ I assume that not all versions of bash behave like that and that on some versions that do, it's just considered an implementation details and not guaranteed, but I wonder if maybe there are at least some bash versions that do explicitly support this and document the condition for this. For instance, if there's a single ; character after the command, without any second command, bash will still execve without forking.
-shellsession
$ pid=$$; bash -c "pstree -p $pid ; "
bash(17516)───pstree(17658)
### Background to my question As I mentioned, this behavior is quite well known1 2 by experienced bash users, and I'm familiar with it for a long time. Some days ago I encountered the following comment to [Interactive bash shell: Set working directory via commandline options](https://unix.stackexchange.com/questions/766111/interactive-bash-shell-set-working-directory-via-commandline-options/766113#comment1461163_766113) where @dave_thompson_085 wrote: > bash automatically execs (i.e. replaces itself with) the last (or only) command in -c. I responded that it's only true if there's a single command. But then I wondered: Are there some versions of bash where maybe the last command **is** execed and not forked, even if there's another command before it? And in general, are there cases this behavior is guaranteed? Do certain bash versions expose (and elaborate on) this feature outside of the source code? ### Additional references * 1[Why is there no apparent clone or fork in simple bash command and how it's done?](https://unix.stackexchange.com/questions/466496/why-is-there-no-apparent-clone-or-fork-in-simple-bash-command-and-how-its-done) * 2[Why bash does not spawn a subshell for simple commands?](https://unix.stackexchange.com/questions/401020/why-bash-does-not-spawn-a-subshell-for-simple-commands)
Asked by aviro (6925 rep)
Jan 10, 2024, 10:43 AM
Last activity: Jan 11, 2024, 08:01 AM