Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z - Internet FAQ Archives

Unix - Frequently Asked Questions (3/7) [Frequent posting]
Section - Why do some scripts start with #! ... ?

( Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Airports ]

Top Document: Unix - Frequently Asked Questions (3/7) [Frequent posting]
Previous Document: How do I get the date into a filename?
See reader questions & answers on this topic! - Help others by sharing your knowledge
Date: Tue, 14 Jul 1992 21:31:54 GMT

3.16) Why do some scripts start with #! ... ?

      Chip Rosenthal has answered a closely related question in
      comp.unix.xenix in the past.

      I think what confuses people is that there exist two different
      mechanisms, both spelled with the letter `#'.  They both solve the
      same problem over a very restricted set of cases -- but they are
      none the less different.

      Some background.  When the UNIX kernel goes to run a program (one
      of the exec() family of system calls), it takes a peek at the
      first 16 bits of the file.  Those 16 bits are called a `magic
      number'.  First, the magic number prevents the kernel from doing
      something silly like trying to execute your customer database
      file.  If the kernel does not recognize the magic number then it
      complains with an ENOEXEC error.  It will execute the program only
      if the magic number is recognizable.

      Second, as time went on and different executable file formats were
      introduced, the magic number not only told the kernel *if* it
      could execute the file, but also *how* to execute the file.  For
      example, if you compile a program on an SCO XENIX/386 system and
      carry the binary over to a SysV/386 UNIX system, the kernel will
      recognize the magic number and say `Aha!  This is an x.out
      binary!' and configure itself to run with XENIX compatible system

      Note that the kernel can only run binary executable images.  So
      how, you might ask, do scripts get run?  After all, I can type
      `my.script' at a shell prompt and I don't get an ENOEXEC error.
      Script execution is done not by the kernel, but by the shell.  The
      code in the shell might look something like:

        /* try to run the program */
        execl(program, basename(program), (char *)0);

        /* the exec failed -- maybe it is a shell script? */
        if (errno == ENOEXEC)
            execl ("/bin/sh", "sh", "-c", program, (char *)0);

        /* oh no mr bill!! */
        return -1;

            (This example is highly simplified.  There is a lot
            more involved, but this illustrates the point I'm
            trying to make.)

      If execl() is successful in starting the program then the code
      beyond the execl() is never executed.  In this example, if we can
      execl() the `program' then none of the stuff beyond it is run.
      Instead the system is off running the binary `program'.

      If, however, the first execl() failed then this hypothetical shell
      looks at why it failed.  If the execl() failed because `program'
      was not recognized as a binary executable, then the shell tries to
      run it as a shell script.

      The Berkeley folks had a neat idea to extend how the kernel starts
      up programs.  They hacked the kernel to recognize the magic number
      `#!'.  (Magic numbers are 16-bits and two 8-bit characters makes
      16 bits, right?)  When the `#!' magic number was recognized, the
      kernel would read in the rest of the line and treat it as a
      command to run upon the contents of the file.  With this hack you
      could now do things like:

        #! /bin/sh

        #! /bin/csh

        #! /bin/awk -F:

      This hack has existed solely in the Berkeley world, and has
      migrated to USG kernels as part of System V Release 4.  Prior to
      V.4, unless the vendor did some special value added, the kernel
      does not have the capability of doing anything other than loading
      and starting a binary executable image.

      Now, lets rewind a few years, to the time when more and more folks
      running USG based unices were saying `/bin/sh sucks as an
      interactive user interface!  I want csh!'.  Several vendors did
      some value added magic and put csh in their distribution, even
      though csh was not a part of the USG UNIX distribution.

      This, however, presented a problem.  Let's say you switch your
      login shell to /bin/csh.  Let's further suppose that you are a
      cretin and insist upon programming csh scripts.  You'd certainly
      want to be able to type `my.script' and get it run, even though it
      is a csh script.  Instead of pumping it through /bin/sh, you want
      the script to be started by running:

        execl ("/bin/csh", "csh", "-c", "my.script", (char *)0);

      But what about all those existing scripts -- some of which are
      part of the system distribution?  If they started getting run by
      csh then things would break.  So you needed a way to run some
      scripts through csh, and others through sh.

      The solution introduced was to hack csh to take a look at the
      first character of the script you are trying to run.  If it was a
      `#' then csh would try to run the script through /bin/csh,
      otherwise it would run the script through /bin/sh.  The example
      code from the above might now look something like:

        /* try to run the program */
        execl(program, basename(program), (char *)0);

        /* the exec failed -- maybe it is a shell script? */
        if (errno == ENOEXEC && (fp = fopen(program, "r")) != NULL) {
            i = getc(fp);
            (void) fclose(fp);
            if (i == '#')
                execl ("/bin/csh", "csh", "-c", program, (char *)0);
                execl ("/bin/sh", "sh", "-c", program, (char *)0);

        /* oh no mr bill!! */
        return -1;

      Two important points.  First, this is a `csh' hack.  Nothing has
      been changed in the kernel and nothing has been changed in the
      other shells.  If you try to execl() a script, whether or not it
      begins with `#', you will still get an ENOEXEC failure.  If you
      try to run a script beginning with `#' from something other than
      csh (e.g. /bin/sh), then it will be run by sh and not csh.

      Second, the magic is that either the script begins with `#' or it
      doesn't begin with `#'.  What makes stuff like `:' and `: /bin/sh'
      at the front of a script magic is the simple fact that they are
      not `#'.  Therefore, all of the following are identical at the
      start of a script:


        : /bin/sh

                        <--- a blank line

        : /usr/games/rogue

        echo "Gee...I wonder what shell I am running under???"

      In all these cases, all shells will try to run the script with /bin/sh.

      Similarly, all of the following are identical at the start of a script:


        # /bin/csh

        #! /bin/csh

        #! /bin/sh

        # Gee...I wonder what shell I am running under???

      All of these start with a `#'.  This means that the script will be
      run by csh *only* if you try to start it from csh, otherwise it
      will be run by /bin/sh.

            (Note:  if you are running ksh, substitute `ksh' for
            `sh' in the above.  The Korn shell is theoretically
            compatible with Bourne shell, so it tries to run these
            scripts itself.  Your mileage may vary on some of the
            other available shells such as zsh, bash, etc.)

      Obviously, if you've got support for `#!' in the kernel then the
      `#' hack becomes superfluous.  In fact, it can be dangerous
      because it creates confusion over what should happen with `#! /bin/sh'.

      The `#!' handling is becoming more and more prevelant.  System V
      Release 4 picks up a number of the Berkeley features, including
      this.  Some System V Release 3.2 vendors are hacking in some of
      the more visible V.4 features such as this and trying to convince
      you this is sufficient and you don't need things like real,
      working streams or dynamically adjustable kernel parameters.

      XENIX does not support `#!'.  The XENIX /bin/csh does have the `#'
      hack.  Support for `#!' in XENIX would be nice, but I wouldn't
      hold my breath waiting for it.


End of unix/faq Digest part 3 of 7

Ted Timar -
ISG Technologies Inc., 6509 Airport Road, Mississauga, Ontario, Canada L4V 1S7

User Contributions:

Sep 27, 2021 @ 1:13 pm
Hello ... Im looking a lover..
I love oral sex! Write me -
Oct 3, 2021 @ 2:14 pm
Try Your luck and win a FREE $500 or $1000 coupon! -
Oct 6, 2021 @ 3:15 pm
Hi baby!! my name is Virginia...
I love oral sex! Write me -
Oct 7, 2021 @ 12:00 am
Try Your luck and win a Free Coca-Cola Pack! -
Oct 12, 2021 @ 3:15 pm
WiFiBooster Pro provides you max speed with 300Mbps, no delay for playing game, online transfer files and video chat! Works with Any Router and Device (Smartphone, Computer, Smart tv, etc). Get 50% Off Today! Order Here -
Oct 18, 2021 @ 3:03 am
Fill out the form and win a Free $500 or $1000 voucher! -
Oct 18, 2021 @ 4:16 pm
hey dear!!! my name is Sophia...
I want sex! Here are my photos -
Oct 27, 2021 @ 4:16 pm
Hi !! my name Emily...
Do you want to see a beautiful female body? Here are my erotic photos -
Nov 6, 2021 @ 2:14 pm
heey .. my name Rebecca!!!
I love oral sex! Write me -
Dec 3, 2021 @ 7:19 pm
Hi !! my name Maria.
I love sex. Here are my erotic photos -
Dec 20, 2021 @ 5:05 am
Hi .. Im looking a man!!!
If you want to meet me, I'm here -
Jan 13, 2022 @ 4:16 pm
heey baby!!! my name Margaret..
I want sex! Write me -
Feb 5, 2022 @ 12:12 pm
Hi...?! I'm my name is Name.FirstName and I have
Good opportunity for Target.Name, just follow this link to learn Remote Zoom Hypnosys ::) (Many eyes for better hypnosys)
Rodawg Thepuss
Feb 5, 2022 @ 12:12 pm
Hi, my name is Rodawg Thepuss,Third of the name.
I am here to present you a new and exciting opportunity to take advantage of others with Hypnosis through TeamsMEET.Hypnosis Hypnosis Hypnosis Hypnosis Hypnosis Hypnosis Hypnosis .

This is a record access board which can hold 30 seconds information about all the Hypnosis teams in Singapore. These teams have made numerous activities in the whole of Singapore, which has led to many mass hypnosiemicy readings.

This is the fastest way you can fast way of getting your classmates' goal on term project , S P MOAR!

so join Hypnosis Team in to become team's master key. On my life I swear by the many success stories i have shared above.

To be free of all problems, if you will join my Virtual Talk seminar. No one could ever stop you from achieving success. Hypnosis can transform you into the waifu of your dreams by following the link:
Apr 12, 2022 @ 11:11 am
Hello Folks,

For old Linux distributions I could suggest this web site -
Oct 16, 2022 @ 10:10 am
side effects of stopping buspar inhese
Apr 3, 2023 @ 9:09 am
Regards, An abundance of posts!
funny college essay newsletter writing service
Apr 4, 2023 @ 2:02 am
You actually explained that well.
master thesis writer custom thesis writing service
Nathan Higgurs
Apr 20, 2023 @ 2:14 pm
There sure are a lot of spam comments on this page.
Sep 29, 2023 @ 3:03 am
hallo dear... Im looking a man.
I want sex! Write me -
Oct 1, 2023 @ 4:04 am
Thanks for the command name lore.
The bot comments are hilarious as well ;)
Tomak Zain Zarif
Nov 14, 2023 @ 1:01 am
I'm looking to get assistance for houseing please help me community others nowhere else to turn and I've exosted all leads. I'm diabetic,with narapathy in my feet and hands.I'm a strong black man 46 years of age just had birthday Nov.3/which makes me a humbled Scorpio until you piss me off#1im a born and raises decent of Los Angle Cali. If you want to call or email me hit me up #1 @ I defianately need a woman in my life. Hit me soon#1

Comment about this article, ask questions, or add new information about this topic:

Top Document: Unix - Frequently Asked Questions (3/7) [Frequent posting]
Previous Document: How do I get the date into a filename?

Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Single Page

[ Usenet FAQs | Web FAQs | Documents | RFC Index ]

Send corrections/additions to the FAQ Maintainer: (Ted Timar)

Last Update March 27 2014 @ 02:12 PM