Why do all script files start with
#!/bin/sh
or with
#!/bin/csh
Is that required? What's the purpose of this? And what's the difference between the two?
Why do all script files start with
#!/bin/sh
or with
#!/bin/csh
Is that required? What's the purpose of this? And what's the difference between the two?
The
#!
line tells the kernel (specifically, the implementation of theexecve
system call) that this program is written in an interpreted language; the absolute pathname that follows identifies the interpreter. Programs compiled to machine code begin with a different byte sequence -- on most modern Unixes,7f 45 4c 46
(^?ELF) that identifies them as such.You can put an absolute path to any program you want after the
#!
, as long as that program is not itself a#!
script. The kernel rewrites an invocation ofwhere
./script
starts with, say,#! /usr/bin/perl
, as if the command line had actually beenOr, as you have seen, you can use
#! /bin/sh
to write a script intended to be interpreted bysh
.The
#!
line is only processed if you directly invoke the script (./script
on the command line); the file must also be executable (chmod +x script
). If you dosh ./script
the#!
line is not necessary (and will be ignored if present), and the file does not have to be executable. The point of the feature is to allow you to directly invoke interpreted-language programs without having to know what language they are written in. (Dogrep '^#!' /usr/bin/*
-- you will discover that a great many stock programs are in fact using this feature.)Here are some rules for using this feature:
#!
must be the very first two bytes in the file. In particular, the file must be in an ASCII-compatible encoding (e.g. UTF-8 will work, but UTF-16 won't) and must not start with a "byte order mark", or the kernel will not recognize it as a#!
script.#!
must be an absolute path (starts with/
). It cannot contain space, tab, or newline characters.#!
and the/
. Do not put more than one space there.#!
line, they will not be expanded.#! /usr/bin/awk -f
), sometimes it's just useful (#! /usr/bin/perl -Tw
). Unfortunately, you cannot put two or more arguments after the absolute path.#! /usr/bin/env interpreter
instead of#! /absolute/path/to/interpreter
. This is almost always a mistake. It makes your program's behavior depend on the$PATH
variable of the user who invokes the script. And not all systems haveenv
in the first place.setuid
orsetgid
privileges can't use#!
; they have to be compiled to machine code. (If you don't know whatsetuid
is, don't worry about this.)Regarding
csh
, it relates tosh
roughly as Nutrimat Advanced Tea Substitute does to tea. It has (or rather had; modern implementations ofsh
have caught up) a number of advantages oversh
for interactive usage, but using it (or its descendanttcsh
) for scripting is almost always a mistake. If you're new to shell scripting in general, I strongly recommend you ignore it and focus onsh
. If you are using acsh
relative as your login shell, switch tobash
orzsh
, so that the interactive command language will be the same as the scripting language you're learning.This is known as a
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
A shebang is only relevant when a script has the execute permission (e.g. chmod u+x script.sh).
When a shell executes the script it will use the specified interpreter.
Example:
This defines what shell (command interpreter) you are using for interpreting/running your script. Each shell is slightly different in the way it interacts with the user and executes scripts (programs).
When you type in a command at the Unix prompt, you are interacting with the shell.
E.g.,
#!/bin/csh
refers to the C-shell,/bin/tcsh
the t-shell,/bin/bash
the bash shell, etc.You can tell which interactive shell you are using the
command, or alternatively
You can change your command shell with the
chsh
command.Each has a slightly different command set and way of assigning variables and its own set of programming constructs. For instance the if-else statement with bash looks different that the one in the C-shell.
This page might be of interest as it "translates" between bash and tcsh commands/syntax.
Using the directive in the shell script allows you to run programs using a different shell. For instance I use the
tcsh
shell interactively, but often run bash scripts using /bin/bash in the script file.Aside:
This concept extends to other scripts too. For instance if you program in Python you'd put
at the top of your Python program