I have seen this question on this site and this prompted me to ask this question . I want to know in Unix speak what is the difference between an executable and a shell script ?
An executable refers to any file with the executable bit set that could be executed (even if there are errors in the actual running of the program).
A shell script is a specific type of executable that is intended to be interpreted by a shell using the
#! directive to specify an interpreter.
A script is a file which:
- is human-readable (at least to a reasonably trained human, i.e. the file consists of printable characters); and
- is understood by an interpreter as instructions describing the behavior of a program.
A shell script is a script whose interpreter is a shell. In the unix world, “shell” refers to the family of shells that resemble the Bourne shell; modern such shells (ash, bash, ksh, zsh, …) conform to the POSIX shell standard. More generally, the word “shell” can include other command interpreters such as csh, tcsh, fish, …
An executable is any file that can be executed. In order to be effectively executable, a file needs to have two properties:
- The user must have the permission to execute it. This can be seen with the command
ls -l: the
xcharacter must be present in the permission column.
The format of the file must be one that the system recognizes as executable. Executable formats can be divided into several categories:
- Native executables, which consist of machine code organized according to the operating system's binary executable layout. Most modern unix systems use the ELF format for their native executables.
- Scripts. An executable script is a file begins with a shebang line, consisting of the two characters
#!followed by a path to a file. To execute such a file, the kernel executes the interpreter program and passes it the path to the script as an argument.
- Possibly other formats depending on the system. For example, Linux can register arbitrary file formats through the binfmt_misc facility. This allows Java bytecode files to be executed through a registered JVM, Windows executables to be executed through Wine, etc.
Note that being an executable is dependent on the system. For example, an amd64 Linux binary is executable on an amd64 Linux system but not on a 32-bit system. A binary for Android is not executable on a normal Linux installation. A Windows executable is only executable on Linux if Wine is present. A script that begins with
#!/usr/local/bin/ruby is only executable if there is a program located at
A shell script usually is executable. But it can be non-executable, if you do not have the permission to execute it. You can still have it interpreted by passing it explicitly to the interpreter (e.g.
bash /path/to/script) — “have it interpreted” is a fancy way of saying “execute”.
A shell script is a series of command that will be interpreted by a shell (Usually sh or a sh-compatible shell, sometimes another.)
The script name can, but does NOT need to, end in ".sh" or ".bash" or ".csh" etc (giving an hint as to the shell it should be launched by).
For clarity I'll assume: that the script name is
script, and the shell it should be launched in is
A typical way to launch it in shell would then be :
bash /absolute/path/to/the/script or
bash ./relative/path/to/the/script. That way, it doesn't need to have the executable bit set, as it is only read by bash, which then executes the content.
It can also be set +x (executable) to allow to launch it directly from your current shell session with: /absolute/path/to/the/script (or ./relative/path/to/the/script). Beware: by default, when launched that way, it is launched via the shell you typed in or via a posix shell (the behavior is OS dependent), so it could possibly not be the shell it's supposed to be run by. That's why you can (and should) specify as the first line of the script : #!/path/to/good/shell which indicates to your OS that that script should really be launched by /path/to/good/shell instead.
An executable is a file that has the "x" bit set for the user(s)/group(s) it is supposed to be launched by. It can be typically a "binary", or a script.
file /some/file can tell you more about the file's content. Try
file /usr/bin/bash or
file /etc/profile to see some examples.