bash – Difference Between Sourcing and Executing a File

bashshell

What's the difference between executing a script like this:

./test.sh

and executing a script like this:

. test.sh?

I tried a simple, two-line script to see if I could find if there was a difference:

#!/bin/bash
ls

But both . test.sh and ./test.sh returned the same information.

Best Answer

./test.sh runs test.sh as a separate program. It may happen to be a bash script, if the file test.sh starts with #!/bin/bash. But it could be something else altogether.

. ./test.sh executes the code of the file test.sh inside the running instance of bash. It works as if the content file test.sh had been included textually instead of the . ./test.sh line. (Almost: there are a few details that differ, such as the value of $BASH_LINENO, and the behavior of the return builtin.)

source ./test.sh is identical to . ./test.sh in bash (in other shells, source may be slightly different or not exist altogether; . for inclusion is in the POSIX standard).

The most commonly visible difference between running a separate script with ./test.sh and including a script with the . builtin is that if the test.sh script sets some environment variables, with a separate process, only the environment of the child process is set, whereas with script inclusion, the environment of the sole shell process is set. If you add a line foo=bar in test.sh and echo $foo at the end of the calling script, you'll see the difference:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar