I have a Bash script that may either be executed directly or sourced into the current shell. When it finishes, I need it to use `return` in the sourced case and `exit` when run as a standalone script. One way to detect whether it was sourced is `(return 0 2>/dev/null)`, but that seems to encourage extra branching. I'm wondering whether this is safe: `return "$exitcode" 2>/dev/null; exit "$exitcode"`. What edge cases or unexpected behavior could this cause?
3 Answers
Be careful about where this code appears. `return` is determined by its execution context, not simply by whether the file was sourced. Inside a function, `return` is valid and succeeds whether the script was sourced or executed, so an `exit` placed afterward will never run. The fallback pattern only distinguishes the two cases when it is used at the file’s top level, outside any function.
If the conditional behavior is needed at top level, you can intentionally rely on `return` failing when the file is executed directly: `return "$e" 2>/dev/null || exit "$e"`. In a sourced file, `return` succeeds and the `exit` is skipped; when executed directly, the failed `return` allows the `exit` to run.
A common approach is to put the script’s main body in a function. Then you can always use `return` inside that function, regardless of how the file was started. At the bottom, invoke the function and use its status for the standalone case, such as `main "$@"; exit $?`. This keeps the sourced-versus-executed distinction in one place instead of spreading it through the script.

That can make the file structure less convenient, especially if it already contains several functions. Still, wrapping at least the main execution flow this way may be a reasonable compromise.