The difference between sourcing (. test.sh
) the script and running it (test.sh
or ./test.sh
) is in the first line.
If you source the script the first line is only a comment and ignored. But if you run it, the first line is examined by the kernel for the first two characters, and if they are "#!
", the rest of the line will be used as the path and the first argument for an interpreter. That is the kernel will look for an executable named /bin/bash
and pass it the name of the script as first argument. Like this: /bin/bash ./test.sh
.
This is what normally would happen and you are right, it should have the same effect for your script. But your script contains a problem: The first line ends with a DOS line ending (CR LF) instead of a unix line ending (LF). So the name of the interpreter, as the kernel sees it is /bin/bash^M
which does not exist on your disk (^M stands for the spurious CR before the line ending). To make matters worse, the ^M character is usually invisible.
You can prove that this is the case with cat -v test.sh
(which prints the substitution ^M for the invisible CR character).