source (a synonym to
. (dot) will
execute commands in the current environment
that is, it will not execute
test.sh in a new shell with its own variables, but just run every command in it in your current shell. In particular, this makes your
#!/bin/bash -e shebang ineffective, it's treated as a comment. If you were to change your script to
sourceing it would immediately exit your interactive session because of the return code of
false. If you are not saving the output of your current shell somewhere, any error messages will be lost by this (that's not so important for just
false, but important to consider for real scripts). I would recommend against using
source in combination with
set -e to run any scripts that might fail.
TEST_VAR=1234; source test.sh persists the value of
TEST_VAR because the
; simply delimits commands, making
TEST_VAR=1234; source test.sh the same as
That's just an assignment to
TEST_VAR followed by a call to
source runs commands in the current environment,
TEST_VAR is available in that environment.
; wasn't there, that would change by making the assignment to
TEST_VAR only effective for the invokation of the
$ cat test.sh
$ TEST_VAR=1234 source test.sh
$ source test.sh
env | grep -i test_var returns nothing also
The reason for that is explained in https://unix.stackexchange.com/a/268258/4699:
env is an external command (in contrary to shell built in commands) and for this reason, env only prints variables that are
exported from the shell.
set on the other side lists all shell variables. Some of them are exported.
export lists the shell variables that are exported by the shell.
export can also be used to export an already-set variable:
$ TEST_VAR=1234; source test.sh
$ set | grep TEST
$ env | grep TEST
$ export TEST_VAR
$ env | grep TEST