3

I have bash script test.sh which does nothing special:

#!/bin/bash
echo Hello!

If I run it like this . test.sh, it works.

kopparberg:dev marek$ . test.sh
Hello!

If I run it like this ./test.sh, it does not.

kopparberg:dev marek$ ./test.sh 
-bash: ./test.sh: /bin/bash^M: bad interpreter: No such file or directory

What is the difference?

2 Answers 2

6

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).

3

The fist solution is an alias for "source" command.

The shebang is considered like a #comment for source

When you call the script with ./script, the shell will execute the script with the shebang #!/bin/bash

The error you gave seems to be a CRLF problem, you can run :

dos2unix script.sh

to remove Windows end-lines.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .