0

What is the difference between #/bin/sh and # ! /bin/sh ? and #/bin/bash in shell script file? I am new to the shell script, I want to create a shell script file which will run the code.

tripleee
  • 175,061
  • 34
  • 275
  • 318

2 Answers2

1

On Linux (and several other POSIX systems) the #! (called shebang and without spaces) is understood by execve(2) when it is the first line of some executable script and immediately followed by some executable file (called interpreter).

If you use Linux, read Advanced Linux Programming then syscalls(2)

Spaces (actually lack of most of them) are important.

You might write an executable Python script starting with #!/usr/bin/python. Use chmod(1) to make it executable and see inode(7). You could also have some executable GNU guile script.

On some Linux distributions, /bin/sh is a symlink(7) to /bin/bash (that is GNU bash). But on others, to /bin/dash (see DASH website). This explains some differences between them.

And GNU bash has a documented behavior. So read its documentation.

And GNU bash is free software.

So you are allowed to study its source code and improve it.

Also, dash is (like sash) open source. You can study its source code and improve it.

Read also Advanced Linux Programming then syscalls(2) and bash(1).

Notice that /bin/sh is documented in POSIX standards.

My favorite Linux shell is zsh. You could try fish (coded in C++, open source) or es, and set your login shell with chsh(1) (see passwd(5) and shells(5)...)

As an exercise, you could even write your own Unix shell. You could want to use GNU readline inside it. See also path_resolution(7) and glob(7).

You certainly would learn a lot by reading the source code of your favorite shell.

Some shells accept plugins (see dlopen(3) and dlsym(3)...). You could write one for them.

I want to create a shell script file which will run the code.

I recommend to use both GNU emacs and git for that purpose. But keep your shell script small. For large scripts (more than a few hundred lines), use something better than GNU bash.

In some cases, a shell script is generated. An example of such generator is GNU autoconf.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

The first two bytes in a file make up an 16-bit-integer known as magic number, from which the operating system can derive how to handle this file. For certain magic numbers, the subsequent bytes are used to further differentiate into more detail. The magic number (written in hex) 2321 defines that this is a textfile which can be executed by some language processor (bash, perl, m4,....), and the subsequent bytes denote the language processor to be actually used. If you look up 2321 in the ASCII table, it is #!.

Your other two examples don't denote a valid magic number.

You don't need to provide the #! line if you don't want to (though it is often a good idea to do so), since you can always, when executing a script, write explicitly how it is to be processed.

For instance, if you have a file foo which is supposed to be run by bash, you can either start it with i.e. (depending on where bash is located on your system)

#!/usr/bin/bash

or, if you want bash to be located via your PATH, by

#!/usr/local/bin/env bash

and set the executable bit on your script,

chmod u+x foo

and then invoke the script by simply typing

./foo

or don't do any of this preparation work and invoke your script by

bash ./foo

UPDATE : As triplee pointed out, the solution involving env should be better written as

#!/usr/bin/env bash

even if /usr/local/bin happens to exist on your platform, because it makes porting the scripts to different hosts easier (/usr/bin/env is supposed to exist in hopefully any Linux- or BSD-setting, including MacOS).

user1934428
  • 19,864
  • 7
  • 42
  • 87
  • Maybe emphasize that `#` when not immediately followed by `!` is just a comment. – tripleee Nov 26 '20 at 08:30
  • `#!/usr/local/bin/env` will most probably not exist; most places these days the correct shebang would be `#!/usr/bin/env` – tripleee Nov 26 '20 at 08:30
  • @tripleee : That's why I mentioned that the OP has to adopt the pathes to his environment. I just copied the setup from my own environment for laziness, where the `env` is in `/usr/local/bin` and in `/usr/bin`. I agree that in particular with `env`, for compatibility with other platforms `/usr/bin` would be the preferred choice, and I will update my answer correspondingly. – user1934428 Nov 26 '20 at 08:49