1

Is there something between exit and return 1 in bash? Some command that would guarantee stop of further processing but not exit terminal?

Meaning if I use exit in a sourced function in my bash anytime exit is invoked it will actually quit bash (or log off of ssh connection if I am on remote host). If I use return 1 then I have to check the value in the calling function.

With return I have to write code like the following:

foo(){
  if [[ "$#" -ne 1 ]]; then
    echo "Unexpected number of arguments [actual=$#][expected=1]"
    return 1
  fi

  # ... do stuff.
}

bar(){
  foo
  if [[ "$?" -ne 0 ]]; then
    echo "Line:$LINENO failure"
    return 1;
  fi

  # do stuff only when foo() is successful
}

I could use an exit but as described then I will quit my current bash if the operation is not succesful:

foo(){
  if [[ "$#" -ne 1 ]]; then
    echo "Unexpected number of arguments [actual=$#][expected=1]"
    exit
  fi

  # ... do stuff.
}

bar(){
  foo
  # do stuff only when foo() is successful
}

What I would like is something like:

foo(){
  if [[ "$#" -ne 1 ]]; then
    echo "Unexpected number of arguments [actual=$#][expected=1]"
    # Simulate CTRL+C press (to cause everything to halt but not exit terminal)
    # Like an exception throw or something?
  fi

  # ... do stuff.
}

bar(){
  foo
  # do stuff only when foo() is successful
}

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
user7858768
  • 838
  • 7
  • 22
  • If you don't want your terminal to exit when your shell exits, *run the shell under a different shell*, with the outer shell configured to pause and let the user inspect, or whatever other specific behavior you happen to want. – Charles Duffy Aug 15 '19 at 01:37
  • @hanshenrik, ...what's that supposed to illustrate, and why is it expected to be useful? It's very unlikely that the stdout of running bash is going to be a useful exit code; and capturing stdout rather than letting it flow through to the terminal constrains what can be done with it in the underlying scripts. – Charles Duffy Aug 15 '19 at 01:38
  • 1
    *If I use return 1 then I have to check the value in the calling function* -- yes, that's what you're supposed to do, **always**. If you're writing C or Go, you always explicitly check exit status, right? Good bash code does the same. (Idioms like `foo || die "foo failed"` can make that easy). There exist facilities that were designed with the intention of making that unnecessary, but [they do their jobs very badly](http://mywiki.wooledge.org/BashFAQ/105#Exercises) and shouldn't be used. – Charles Duffy Aug 15 '19 at 01:40
  • Pressing ctrl-C does not "cause everything to halt". it just sends a SIGINT to the foreground process group. – William Pursell Aug 15 '19 at 01:45
  • Possibly use `sleep infinity`, see: https://stackoverflow.com/a/22100106/7939871 – Léa Gris Aug 15 '19 at 03:31

4 Answers4

0

With return I have to write code like the following:

bar() {
  foo
  if [[ "$?" -ne 0 ]]; then
    echo "Line:$LINENO failure"
    return 1;
  fi

  # do stuff only when foo() is successful
}

Explicitly checking $? can usually be avoided. You can shorten the above to:

bar() {
  foo || return
  # do stuff only when foo() is successful
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
0

You just run a command as the if expression. If will check the return code and if it is 0 will evaluate true. If it is non 0 will evaluate false.

He is some sample code.

$ foo() { return 0; }
$ if foo
> then 
>   echo hello
> else 
>   echo good bye
> fi
hello

$ foo() { return 1; }
$ if foo
> then 
>   echo hello
> else 
>   echo good bye
> fi
good bye
WaltDe
  • 1,715
  • 8
  • 17
0

You really should just check the exit value. But, if you want to return when the shell is interactive and exit otherwise, in bash you could do:

foo() {
        case $- in
        *i*) return 1;;
        *) exit 1;;
        esac
}
William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

What I was looking for is kill -INT -$$ which interrupts the current process but does not exist the current shell (unlike exit 1). Which allows kill -INT -$$ to be use in command line shell.

user7858768
  • 838
  • 7
  • 22