Alex Ryan
Alex Ryan

Reputation: 3819

How to exit a bash shell script from within curly braces?

I have a need to group commands using curly braces in my shell script so that I can direct their output to separate log files like so ...

 😈   >cat how-to-exit-script-from-within-curly-braces.sh 

{
  printf "%d\n" 1
  printf "%d\n" 2
} | tee a.log
{
  printf "%d\n" 3
  printf "%d\n" 4
} | tee b.log

 😈   >./how-to-exit-script-from-within-curly-braces.sh 
1
2
3
4
 😈   >cat a.log 
1
2
 😈   >cat b.log 
3
4
 😈   >

Although I have added the curly braced to facilitate logging, I would still like the script to exit when the exit command is invoked inside the curly braces.

It does not do so of course. It only exits the curly braces and then continues on executing the remainder of the script like so ...

 😈   >cat how-to-exit-script-from-within-curly-braces.sh 

{
  printf "%d\n" 1
  exit
  printf "%d\n" 2
} | tee a.log
{
  printf "%d\n" 3
  printf "%d\n" 4
} | tee b.log

 😈   >./how-to-exit-script-from-within-curly-braces.sh 
1
3
4
 😈   >cat a.log 
1
 😈   >cat b.log 
3
4
 😈   >

making the exit code non-zero and adding "set -e" to the script does not appear to work ...

 😈   >cat how-to-exit-script-from-within-curly-braces.sh 
set -e

{
  printf "%d\n" 1
  exit 1
  printf "%d\n" 2
} | tee a.log
{
  printf "%d\n" 3
  printf "%d\n" 4
} | tee b.log

 😈   >./how-to-exit-script-from-within-curly-braces.sh 
1
3
4
 😈   >cat a.log 
1
 😈   >cat b.log 
3
4
 😈   >

Is there a way to force the exit of the script from within the curly braces?

Upvotes: 4

Views: 1379

Answers (1)

that other guy
that other guy

Reputation: 123470

There is no problem with exit and curly braces:

{
  exit
}
echo "This will never run."

However, there is a problem with exit and pipes, and that's what you're running into:

exit | exit
echo "Still alive"

In bash by default, each stage in a pipeline runs in a subshell, and exit can only exit that subshell. In your case, you can use redirection and process substitution instead:

{
  printf "%d\n" 1
  exit 1
  printf "%d\n" 2
} > >(tee a.log)
echo "This will not run"

Note that this is bash specific code, and will not work in sh (such as when using #!/bin/sh or sh myscript). You have to use bash instead.

Upvotes: 6

Related Questions