#! http://people.csail.mit.edu/jaffer/Docupage/sharpbang.html

#! (sharp-bang)

Current Version Released Terms
1.1 2002 Public Domain

Quick Start

Unix Shell Scripts

file: #! interpreter arg

On Unix systems, a Shell-Script is a file (with execute permissions) whose first two characters are `#!'. The interpreter argument must be the valid pathname to an executable program. The directories named by environment variable PATH are not searched to find interpreter. (If the file interpreter does not exist or is not executable, then the Unix flags an error.)

If the file interpreter is a binary executable, then the operating system invokes interpreter with a single argument encapsulating the rest of the first line's contents (if not just whitespace), the pathname of the script file, and then any arguments which the shell-script was invoked with.

If the file interpreter is not a binary executable, then it is ignored and the contents of script file are piped (stdin) to /bin/sh.

Unix scripts suffer from several drawbacks:

  1. Some Unixes limit the length of the `#!' interpreter line to the size of an object file header, which can be as small as 32 bytes.
  2. A full, explicit pathname must be specified, perhaps requiring more than 32 bytes and making scripts vulnerable to breakage when programs are moved.
  3. Although Linux will fail to execute a script whose interpreter file does not exist; if that file is not an ELF binary, Linux will not execute that interpreter anyway! It will just feed the (calling) script to /bin/sh.

The distinction between binary and non-binary interpreters was a bad idea originally, and remains so. Whether a file can be executed as a `#!' script depends on whether or not the referenced interpreter is a binary file.

If a system administrator wraps a binary program with a shell or Perl script, then scripts invoking that program will cease to work.


A small (C) program named #! can almost entirely fix Unix scripting.

The first line of the shell script file should invoke the #! program with the name of the desired interpreter (for example freewrl):

#! /usr/local/bin/#! freewrl

When this shell script is executed, freewrl will be called with the path of the invoking shell script as its argument; followed by any arguments passed to the shell script.

The interpreter need not be a full path; the directories named by the PATH environment variable are searched in the usual manner.

The #! program thus fixes problems 2 and 3.

On platforms with limited interpreter line-length, the #! script could be placed in `/bin/#!' or even `/#!' to leave more room for the interpreter name. The #! program does not need to be in the search PATH. It is called only by its full path.

Obfuscated C Version

     char*      g(s,t)          char
     * s ;      char*t         ;{int
     l  =       strlen         (s);s
=realloc(s,l+strlen(t)+1);     strcat
    (s +l       ,t );          return
    s ; }        main          (c,v)
    int c       ;char          **v;{
int j=1;char*m=calloc(j,j)     ;for(
    ;j<c;j     ++)m=g           (g(
    m,v[j]     )," ");         
    return     system          (m);}

I am a guest and not a member of the MIT Computer Science and Artificial Intelligence Laboratory.  My actions and comments do not reflect in any way on MIT.
Copyright 2002 Aubrey Jaffer
Go Figure!