Bash script file extension [duplicate]

I have a server where I have different kinds of scripts.

Those scripts are to be opened with different shells such as:

sh ./do_one_thing.sh
bash ./do_another_thing.sh

the .sh extension is dangerous to me especially if I have not connected to the server for a longer time. Or if someone unfamilliar needs to do a stand-in.
I might accidently execute sh ./do_another_thing.sh

Will it make any difference if I name my script do_another_thing.bash? This would create one more layer of foolproofness.

Additionally, I would like to know what the shebang line in the beginning is for other than a reminder to the Admin (#!/bin/bash) if it get's overwritten by sh ./do_another_thing.sh anyways. It seems to me such that there must be a more proper way of executing the script, recogniting the shebang.


Solution 1:

The shebang at the top of the file defines what interpreter is run when you run ./name_of_file (assuming it's executable).

#!/bin/cat
test 123

will simply print the above file when you run it with ./name_of_file, as it will run cat name_of_file.

#!/bin/echo
hello, world

will simply print name_of_file, because it runs echo name_of_file.

Setting that to bash or sh will allow you to choose what interpreter it runs with, as long as you remember to invoke it with ./name_of_file.

That being said, using .sh for sh, and .bash for bash works fine, albiet non-standard. File extensions are fairly fluid on linux.

Solution 2:

The shebang line defines the interpreter, in this case /bin/bash. If you're always going to use the same interpreter for a single script, this is where you define that, which saves you from having to define it in your command. It doesn't make sense to use the shebang to define an interpreter that you don't want to use for that script.

I don't really understand how one extension is more dangerous than another or how you can accidentally type all of that. If you're using tab completion, either extension will autocomplete, so that doesn't protect against clumsiness. The extension is helpful so you can identify/remember what kind of file it is.

In any case, it doesn't matter what you name the script. It doesn't even need an extension.

There's a good question on Unix&Linux that has more information about this.

Solution 3:

If the name of a file with execute permission bits set is typed on the command line, or if the name of such a file is passed to one of the exec*() variant calls of the C runtime library, the Linux kernel will attempt to load and execute it.

The first thing the Linux kernel does is read the first few bytes of the file, looking for known "magic" sequences. One of those magic sequences can also be interpreted as the ASCII string "#!" also known as "hash bang" and shortened to "shebang". When the loader sees that, it will interpret the remainder of the line as the name of another file to exec, passing the first file as an argument. Another magic value is "\x7fELF" which is a classic binary executable file like, say, /bin/sh itself. Note that the default for the kernel loader, if the file has no recognizable magic, is to exec /bin/sh and pass it the name of the file as the first argument -- the equivalent of having a shebang of "#!/bin/sh".

In effect, marking the script as executable using chmod +x ./do_one_thing.sh together with a shebang of "#!/bin/sh" is the equivalent of sh ./do_one_thing.sh. The "file extension" or other DOS concepts are really irrelevant outside of DOS, its ancestral OSes like CP/M, and its descendant OSes like Microsoft Windows.

If you want the best level of foolproofness, mark the files as executable and use the appropriate shebang. Don't rely on humans to do the right thing.