Echo Kilo has asked for the wisdom of the Perl Monks concerning the following question:

Is it accurate to say, the line #!/usr/bin/perl is a command to the Perl program? Is this considered a perl directive like a shell directive or is it something else in perl?

Replies are listed 'Best First'.
Re: Perl Directive
by gaal (Parson) on Dec 13, 2004 at 06:31 UTC
    There is also the obscure benefit of protecting yourself slightly from lineending difficulties: if you write your script on a machine with DOS newlines, and move it to unix in binary mode, you might get an annoying error such as:

    ./myscript.pl: Command not found.

    This is because the first line is something like: #!/usr/bin/perl^M

    ("Something like" meaning perhaps you assumed your perl was in another path.) The command that isn't found is perl^M, but the shell's error message can be infuriatingly misleading. At least the first few times your run into it. If you instead get into the habit of always turning on warnings from the shebang line, #!/usr/bin/perl -w^M

    ...then the OS kernel loads #!/usr/bin/perl correcty, and perl itself is smart enough to do the right thing about subsequent DOS lineendings. Also, you get warnings turned on :)

      Good point.

      If you don't want to specify -w on the shebang line, you can get the same effect with "--":

      #!/usr/bin/perl --^M
Re: Perl Directive
by sgifford (Prior) on Dec 13, 2004 at 05:45 UTC
    It serves two purposes under Unix, and one under Windows. On Unix, executable files starting with #! are run with whatever comes after the #! (pronounced "shebang") as their interpreter. Once Perl starts up, it looks at this first line again, and adds in any command-line options from this line it doesn't already have.
      Furthermore, perl will launch the specified program with the script as input if it doesn't see "perl" in the commmand. This was discussed here.
Re: Perl Directive
by superfrink (Curate) on Dec 13, 2004 at 07:37 UTC
    I'm going to comment with respect to version 2.2 of the Linux kernel here so some of the follow may not apply to your system or even the modern kernel version. Still I find it really interesting and I think you will too.

    Today Linux's main binary file format is called ELF (Executable and Linking Format). Linux has also supported other binary formats, these are options in your kernel setup.

    When you go to run a file as if it were a program the file is checked to see if you have the execute permission on it. After that check the kernel tries to match the file to a known format (ELF, a.out, and so on). This matching is done by looking for "magic numbers" in the file somewhere. I think Microsoft DOS .EXE files always start with the the first two bytes being the ASCII letters "MZ" for example.

    The last check in the list of file formats is for a file that starts with "#!" because this has been used for years in Unix-like systems to mean that the kernel should go find the filename specified after the "#!" and run that program. The name of the file you actually tried to execute gets passed as an argument to the process really created from the "#!" filename.

    Though it is not often done (that I know of) you can actually tell Linux to match executable file formats based on a filename extension like DOS and I think windows does for .EXE files. (I don't know how Windows deals with these things but I think it is based on filename extension. For that matter I don't know how DOS does it either.)

    If you're interested in this look for the binfmt_misc.txt file in the Documentation directory in the kernel source tarball. Before you do decide to use it I caution that I don't know of any companies that use it as a standard. The "#!" line is going to be much more portable.
      to match executable file formats based on a filename extension like DOS and I think windows does for .EXE files. (I don't know how Windows deals with these things but I think it is based on filename extension. For that matter I don't know how DOS does it either.)

      Matching the filename extension is how it is done in DOS (all versions of which I am aware, not just MS-DOS but also compatibles such as PC-DOS and 4DOS) and in the old 3.x versions of Windows (with the winfile.exe file manager), plus all versions of Win95/98/Me (both command.com and also explorer.exe do it this way). You can test this by renaming an .exe file with a different extension and noting that you can no longer execute it, not even by typing the full path, filename, and new extension, not even with the start command. (There is rundll, but that's another matter.)

      In NT (e.g., WinXP), explorer.exe works exactly the same way in this respect as on Win9x. However, I'm less certain about the cmd.exe command interpreter that comes with NT, since I've barely used it. (By the time WinXP came out, I was pretty well entirely switched over to Mandrake already, so I've only seen it at work, and even there my main workstation is Mandrake.)

      However, as noted, Perl on Win32 still reads the shebang line.


      "In adjectives, with the addition of inflectional endings, a changeable long vowel (Qamets or Tsere) in an open, propretonic syllable will reduce to Vocal Shewa. This type of change occurs when the open, pretonic syllable of the masculine singular adjective becomes propretonic with the addition of inflectional endings."  — Pratico & Van Pelt, BBHG, p68

        In Windows NT/2000/XP, it actually works the same way as Unix, that is, by looking for magic numbers in the file.

        There are actually 3 parts of the system that work together -- the NT kernel, the Windows Shell (aka explorer.exe), and the Command Prompt (aka cmd.exe).

        When you click on a file in the Shell or type its name into the Prompt, the API function ShellExecute() is called, which looks up the file association in the registry and starts the right program to open that file.

        The NT kernel does not care about the file's name. The Kernel is accessed by the API call CreateProcess(), which starts the program by looking for magic numbers (.exe format files start with MZ, .com format files have no magic numbers in them). (The kernel function is actually called NtCreateProcess, but programs should only call CreateProcess because Windows 9x had a different Kernel than the NT family has.)

        You can see this in action by renaming helloworld.exe to helloworld. You will not be able to run it from the Command Prompt, but Perl can still run it with system("helloworld"). If you rename it to helloworld.com, it will still work even though the extension is wrong, because the Kernel does not use the file's name.

enviroment and Shebangs
by Luca Benini (Scribe) on Dec 13, 2004 at 11:04 UTC
    You can also use the she bangs (!#) for manipulation the enviroment. For example assume you want to create a particular enviroment for you script if you use
    #!/usr/bin/perl foreach (keys %ENV){ print $_ . " " . $ENV{$_}."\n"; }

    You obtain the enviroment from which you run the script.
    If you use:
    #!/usr/bin/env -i perl foreach (keys %ENV){ print $_ . " " . $ENV{$_}."\n"; }

    You obtain nothing.
    see info coreutils env
Re: Perl Directive
by Echo Kilo (Acolyte) on Dec 13, 2004 at 06:39 UTC
    Is this still called a shell directive or is it called a Perl Directive? Just want to make sure I learn the lingo properly.

      The lingo-istically correct name for it is "shebang line"

      --
      edan

      I've seen shell directive used. It's a general mechanism used by the kernel to start the proper shell, after all. (And also, you make the file "directly" executable :)

      "Shebang line" is also used a lot, as sgifford notes.