0

For example, I can do this with a subshell:

VAL=$( do_something )

but how do I achieve the same thing with curly braces so the command is NOT executing in a subshell? I.e. this does not work:

VAL={ do_something; }

TIA.

ccbunney
  • 2,282
  • 4
  • 26
  • 42

2 Answers2

0

I'm not sure I understand the reasoning for what you're trying to accomplish, but if you can elaborate a bit more I might be able to help you.

I do recommend reading this fantastic write up about what's actually going on though, and why I don't think you want to invoke a process without a subshell.

However, to try and answer what you've asked:

You can't really run a command inside ${}, except in the fallback clause for when a value is not set (in POSIX sh or bash; might be feasible in zsh, which allows all manner of oddball syntax).

However, you can call cd like this if you really wanted this:

cdr() {
   if (( $# )); then
     command cd "$@"
   else
     local home
     home=$(git rev-parse --show-toplevel 2>/dev/null) || home=$HOME
     command cd "$home"
   fi
}

Note

  • Using a function lets us test our argument list, use branching logic, have local variables, &c.
  • command cd is used to call through to the real cd implementation rather than recursing.
syntaqx
  • 2,636
  • 23
  • 29
0

set -e is kinda stiff. Try something like

trap 'err=$?;
      echo >&2 "ERROR $err in $0 at line $LINENO, Aborting";
      exit $err;' ERR

This is a lot more informative when reading through your logs, and you can put a similar command inside the subshell. Yes, it means adding it inside the subshell... but I often do this sort of thing in function definitions that get called in subshells. Works well.

In use:

$ trap 'echo BOOM' ERR # parent shell trap for demo
$ false                # trigger manually for demo
BOOM
$ x="$( trap 'err=$?;
>             echo >&2 "ERROR $err in $0 at line $LINENO, Aborting";
>             exit $err;' ERR
>       date
>       pwd
>       false
>       echo "I shan't"
> )"
ERROR 1 in bash at line 7, Aborting
BOOM
$ echo "$x"
Thu, Jan 10, 2019  8:35:57 AM
/c/Users/P2759474/repos/Old/deploy_microservices
$

If the outer shell had the same or a similar trap, it would have aborted too, with another message. (It's usually helpful to make the messages different.)


If you just don't like that, then as a clumsy workaround you can drop the data to a tempfile. Here's a script that will do it.

set -ex
{ pwd
  date
  false
  echo "will this happen?"
} > foo
x=$(<foo)
echo "$x"

Put that in a script, it successfully bails.

$: ./sete
+ pwd
+ date
+ false
$: echo $?
1

I'd still use the trap, but the logic works.
I'd also use mktemp, and a trap to delete the temp on exit, etc.... but you get the idea.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
  • Thanks for the informative answer. I was trying to find a way to not add "set -e" or a "trap" statement inside the sub shell though. Maybe there is no way.... – ccbunney Jan 10 '19 at 15:54