-1

I'm a beginner at Linux shell, but I know that this command creates a subshell:

Subshells are typically created using subshell operators or commands such as parentheses (), backticks `, or the $() syntax.

: ${FOO:=$([ "$BAR" = "baz" ] && echo "true" || echo "false" )} 

This could be a problem e.g. in a loop (this is not the case here) but I like to learn how to avoid it. Generally speaking, in the above assignment, can a subshell be avoided using the following?

if [ -z "$FOO" ]; then if [ "$BAR" = "baz" ]; then FOO=true else FOO=false fi fi 
8
  • As for the downvotes on your previous iteration of this question, the popup on the downvote button says "The question doesn't show any research effort; it is unclear or not useful". And that question seemed based pretty much completely on unverified hearsay, which doesn't make for a very useful or well-researched question. (It'd be hearsay from a friend too, not just from an AI, but what with the recent discussion about AI-produced crap on SE sites, it's not surprising that explicitly mentioning AI as a source for some misconception would get even more flak) Commented Jul 4, 2023 at 11:15
  • So let's remove any AI reference, maybe some SE linux nerd doesn't downvote it and respect a linux beginner. Commented Jul 4, 2023 at 11:17
  • Reiterating my comment on the deleted question: This should be trivial to test depending on the shell. In bash, for example, replace true and false with $BASH_SUBSHELL and check the output. Commented Jul 4, 2023 at 11:18
  • @muru thanks, I didn't specified it but it's a posix script. I can test it changing to bash ofc. Commented Jul 4, 2023 at 11:19
  • Well, please do, because the concern of "being a problem in a loop" is completely dependent on the actual shell on how it optimizes subshells. If no forking is involved, as seems to be the case in some shells depending on the command run, it's really not that big of a deal. See also: unix.stackexchange.com/a/421028/70524 unix.stackexchange.com/a/264199/70524 Commented Jul 4, 2023 at 11:30

2 Answers 2

3

Generally speaking, in the above assignment, does a subshell can be avoided using the following?

if [ -z "$FOO" ]; then if [ "$BAR" = "baz" ]; then FOO=true else FOO=false fi fi 

Yes, and that would be the correct way to write it.

: ${FOO:=$([ "$BAR" = "baz" ] && echo "true" || echo "false" )}

Runs a subshell (which in most shells involves the costly forking of a process) and is also wrong for several reasons:

  • That ${FOO...} expansion is unquoted and therefore subject to split+glob, making it at least a DoS vulnerability (that's one of the examples given at Security implications of forgetting to quote a variable in bash/POSIX shells).
  • echo "false" is run if either [ or echo true fails while you want it to be run when [ fails only. a && b || c is no proper substitute for if a; then b; else c; fi.

In the ksh93 shell, the subshell and those issues can be avoided with:

: "${FOO:=${ if [ "$VAR" = baz ]; then echo true else echo false fi }}" 

But that has little advantage over the standard and obvious if statement above.

0

For a cryptic one-liner, I think this would achieve the desired result without sub-shells:

[[ "$BAR" = "baz" ]] && FOO=${FOO-true} || FOO=${FOO-false} 

But I'd go with if....

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.