home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book Home Programming PerlSearch this book

Chapter 19. The Command-Line Interface

This chapter is about aiming Perl in the right direction before you fire it off. There are various ways to aim Perl, but the two primary ways are through switches on the command line and through environment variables. Switches are the more immediate and precise way to aim a particular command. Environment variables are more often used to set general policy.

19.1. Command Processing

It is fortunate that Perl grew up in the Unix world, because that means its invocation syntax works pretty well under the command interpreters of other operating systems, too. Most command interpreters know how to deal with a list of words as arguments and don't care if an argument starts with a minus sign. There are, of course, some sticky spots where you'll get fouled up if you move from one system to another. You can't use single quotes under MS-DOS as you do under Unix, for instance. And on systems like VMS, some wrapper code has to jump through hoops to emulate Unix I/O redirection. Wildcard interpretation is a wildcard. Once you get past those issues, however, Perl treats its switches and arguments much the same on any operating system.

Even when you don't have a command interpreter per se, it's easy to execute a Perl program from another program written in any language. Not only can the calling program pass arguments in the ordinary way, it can also pass information via environment variables and, if your operating system supports them, inherited file descriptors (see "Passing Filehandles" in Chapter 16, "Interprocess Communication". Even exotic argument-passing mechanisms can easily be encapsulated in a module, then brought into your Perl program via a simple use directive.

Perl parses command-line switches in the standard fashion.[1] That is, it expects any switches (words beginning with a minus) to come first on the command line. After that usually comes the name of the script, followed by any additional arguments to be passed into the script. Some of these additional arguments may themselves look like switches, but if so, they must be processed by the script, because Perl quits parsing switches as soon as it sees a nonswitch, or the special "--" switch that says, "I am the last switch."

[1] Presuming you agree that Unix is both standard and fashionable.

Perl gives you some flexibility in where you place the source code for your program. For small, quick-and-dirty jobs, you can program Perl entirely from the command line. For larger, more permanent jobs, you can supply a Perl script as a separate file. Perl looks for a script to compile and run in any one of these three ways:

  1. Specified line by line via -e switches on the command line. For example:

    % perl -e "print 'Hello, World.'"
    Hello, World.

  2. Contained in the file specified by the first filename on the command line. Systems supporting the #! notation on the first line of an executable script invoke interpreters this way on your behalf.

  3. Passed in implicitly via standard input. This method works only when there are no filename arguments; to pass arguments to a standard-input script you must use method 2, explicitly specifying a "-" for the script name. For example:

    % echo "print qq(Hello, @ARGV.)" | perl - World
    Hello, World.

With methods 2 and 3, Perl starts parsing the input file from the beginning--unless you've specified a -x switch, in which case it scans for the first line starting with #! and containing the word "perl", and starts there instead. This is useful for running a script embedded in a larger message. If so, you might indicate the end of the script using the __END__ token.

Whether or not you use -x, the #! line is always examined for switches when the line is parsed. That way, if you're on a platform that allows only one argument with the #! line, or worse, doesn't even recognize the #! line as special, you can still get consistent switch behavior regardless of how Perl was invoked, even if -x was used to find the beginning of the script.

Warning: because older versions of Unix silently chop off kernel interpretation of the #! line after 32 characters, some switches may end up getting to your program intact, and others not; you could even get a "-" without its letter, if you're not careful. You probably want to make sure that all your switches fall either before or after that 32-character boundary. Most switches don't care whether they're processed redundantly, but getting a "-" instead of a complete switch would cause Perl to try to read its source code from the standard input instead of from your script. And a partial -I switch could also cause odd results. However, some switches do care if they are processed twice, like combinations of -l and -0. Either put all the switches after the 32-character boundary (if applicable), or replace the use of -0DIGITS with BEGIN{ $/ = "\0DIGITS"; }. Of course, if you're not on a Unix system, you're guaranteed not to have this particular problem.

Parsing of #! switches starts from where "perl" is first mentioned in the line. The sequences "-*" and "" are specifically ignored for the benefit of emacs users, so that, if you're so inclined, you can say:

#!/bin/sh -- # -*- perl -*- -p
eval 'exec perl -S $0 ${1+"$@"}'
    if 0;

and Perl will see only the -p switch. The fancy "-*- perl -*-" gizmo tells emacs to start up in Perl mode; you don't need it if you don't use emacs. The -S mess is explained later under the description of that switch.

A similar trick involves the env(1) program, if you have it:

#!/usr/bin/env perl
The previous examples use a relative path to the Perl interpreter, getting whatever version is first in the user's path. If you want a specific version of Perl, say, perl5.6.1, place it directly in the #! line's path, whether with the env program, with the -S mess, or with a regular #! processing.

If the #! line does not contain the word "perl", the program named after the #! is executed instead of the Perl interpreter. For example, suppose you have an ordinary Bourne shell script out there that says:

#!/bin/sh
echo "I am a shell script"

If you feed that file to Perl, then Perl will run /bin/sh for you. This is slightly bizarre, but it helps people on machines that don't recognize #!, because--by setting their SHELL environment variable--they can tell a program (such as a mailer) that their shell is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them, even though their kernel is too stupid to do so.

But back to Perl scripts that are really Perl scripts. After locating your script, Perl compiles the entire program into an internal form (see Chapter 18, "Compiling"). If any compilation errors arise, execution does not even begin. (This is unlike the typical shell script or command file, which might run part-way through before finding a syntax error.) If the script is syntactically correct, it is executed. If the script runs off the end without hitting an exit or die operator, an implicit exit(0) is supplied by Perl to indicate successful completion to your caller. (This is unlike the typical C program, where you're likely to get a random exit status if your program just terminates in the normal way.)

19.1.1. #! and Quoting on Non-Unix Systems

Unix's #! technique can be simulated on other systems:

Macintosh

A Perl program on a Macintosh will have the appropriate Creator and Type, so that double-clicking them will invoke the Perl application.

MS-DOS

Create a batch file to run your program, and codify it in ALTERNATIVE_SHEBANG. See the dosish.h file in the top level of the Perl source distribution for more information about this.

OS/2

Put this line:

extproc perl -S -your_switches
as the first line in *.cmd file (-S works around a bug in cmd.exe's "extproc" handling).

VMS

Put these lines:

% perl -mysw 'f$env("procedure")' 'p1' 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8' !
$ exit++ + ++$status != 0 and $exit = $status = undef;
at the top of your program, where -mysw are any command-line switches you want to pass to Perl. You can now invoke the program directly by typing perl program, as a DCL procedure by saying @program, or implicitly via DCL$PATH by using just the name of the program. This incantation is a bit much to remember, but Perl will display it for you if you type in perl "-V:startperl". If you can't remember that--well, that's why you bought this book.

Win??

When using the ActiveState distribution of Perl under some variant of Microsoft's Windows suite of operating systems (that is, Win95, Win98, Win00,[2] WinNT, but not Win3.1), the installation procedure for Perl modifies the Windows Registry to associate the .pl extension with the Perl interpreter.

[2]Er, pardon the technical difficulties...

If you install another port of Perl, including the one in the Win32 directory of the Perl distribution, then you'll have to modify the Windows Registry yourself.

Note that using a .pl extension means you can no longer tell the difference between an executable Perl program and a "perl library" file. You could use .plx for a Perl program instead to avoid this. This is much less of an issue these days, since most Perl modules are now in .pm files.

Command interpreters on non-Unix systems often have extraordinarily different ideas about quoting than Unix shells have. You'll need to learn the special characters in your command interpreter (*, \, and " are common) and how to protect whitespace and these special characters to run one-liners via the -e switch. You might also have to change a single % to a %%, or otherwise escape it, if that's a special character for your shell.

On some systems, you may have to change single quotes to double quotes. But don't do that on Unix or Plan9 systems, or anything running a Unix-style shell, such as systems from the MKS Toolkit or from the Cygwin package produced by the Cygnus folks, now at Redhat. Microsoft's new Unix emulator called Interix is also starting to look, ahem, interixing.

For example, on Unix and Mac OS X, use:

% perl -e 'print "Hello world\n"'

On Macintosh (pre Mac OS X), use:

print "Hello world\n"

then run "Myscript" or Shift-Command-R.

On VMS, use:

$ perl -e "print ""Hello world\n"""

or again with qq//:

$ perl -e "print qq(Hello world\n)"

And on MS-DOS et al., use:

A:> perl -e "print \"Hello world\n\""

or use qq// to pick your own quotes:

A:> perl -e "print qq(Hello world\n)"

The problem is that neither of those is reliable: it depends on the command interpreter you're using there. If 4DOS were the command shell, this would probably work better:

perl -e "print <Ctrl-x>"Hello world\n<Ctrl-x>""
The CMD.EXE program seen on Windows NT seems to have slipped a lot of standard Unix shell functionality in when nobody was looking, but just try to find documentation for its quoting rules.

On the Macintosh,[3] all this depends on which environment you are using. The MacPerl shell, or MPW, is much like Unix shells in its support for several quoting variants, except that it makes free use of the Macintosh's non-ASCII characters as control characters.

[3]At least, prior to release of Mac OS X, which, happily enough, is a BSD-derived system.

There is no general solution to all of this. It's just a mess. If you aren't on a Unix system but want to do command-line things, your best bet is to acquire a better command interpreter than the one your vendor supplied you, which shouldn't be too hard.

Or just write it all in Perl, and forget the one-liners.

19.1.2. Location of Perl

Although this may seem obvious, Perl is useful only when users can easily find it. When possible, it's good for both /usr/bin/perl and /usr/local/bin/perl to be symlinks to the actual binary. If that can't be done, system administrators are strongly encouraged to put Perl and its accompanying utilities into a directory typically found along a user's standard PATH, or in some other obvious and convenient place.

In this book, we use the standard #!/usr/bin/perl notation on the first line of the program to mean whatever particular mechanism works on your system. If you care about running a specific version of Perl, use a specific path:

#!/usr/local/bin/perl5.6.0
If you just want to be running at least some version number, but don't mind higher ones, place a statement like this near the top of your program:
use v5.6.0;
(Note: earlier versions of Perl use numbers like 5.005 or 5.004_05. Nowadays we would think of those as 5.5.0 and 5.4.5, but versions of Perl older than 5.6.0 won't understand that notation.)

19.1.3. Switches

A single-character command-line switch without its own argument may always be combined (bundled) with a switch following it.

#!/usr/bin/perl -spi.bak    # same as -s -p -i.bak
Switches are also known as options or flags. Whatever you call them, here are the ones Perl recognizes:

--

Terminates switch processing, even if the next argument starts with a minus. It has no other effect.

-0OCTNUM
-0

Specifies the record separator ($/) as an octal number. If OCTNUM is not present, the NUL character (that's ASCII character 0, Perl's "\0") is the separator. Other switches may precede or follow the octal number. For example, if you have a version of find(1) that can print filenames terminated by the null character, you can say this:

% find . -name '*.bak' -print0 | perl -n0e unlink

The special value 00 makes Perl read files in paragraph mode, equivalent to setting the $/ variable to "". The value 0777 makes Perl slurp in whole files at once. This is equivalent to undefining the $/ variable. We use 0777 since there is no ASCII character with that value. (Unfortunately, there is a Unicode character with that value, \N{LATIN SMALL LETTER O WITH STROKE AND ACUTE}, but something tells us you won't be delimiting your records with that.)

-a

Turns on autosplit mode, but only when used with -n or -p. An implicit split command to the @F array is done as the first thing inside the implicit while loop produced by the -n and -p switches. So:

% perl -ane 'print pop(@F), "\n";'
is equivalent to:
LINE: while (<>) {
    @F = split(' ');
    print pop(@F), "\n";
}
A different field separator may be specified by passing a regular expression for split to the -F switch. For example, these two calls are equivalent:
% awk -F: '$7 && $7 !~ /^\/bin/' /etc/passwd
% perl -F: -lane 'print if $F[6] && $F[6] !~ m(^/bin)' /etc/passwd

-c

Causes Perl to check the syntax of the script and then exit without executing what it's just compiled. Technically, it does a bit more than that: it will execute any BEGIN or CHECK blocks and any use directives, since these are considered to occur before the execution of your program. It no longer executes any INIT or END blocks, however. The older but rarely useful behavior may still be obtained by putting:

BEGIN { $^C = 0; exit; }
at the end of your main script.

-C

Enables Perl to use the native wide-character APIs on the target system, if supported (as of version 5.6.0 it works on Microsoft platforms only). The special variable ${^WIDE_SYSTEM_CALLS} reflects the state of this switch.

-d

Runs the script under the Perl debugger. See Chapter 20, "The Perl Debugger".

-d:MODULE

Runs the script under the control of a debugging or tracing module installed in the Perl library as Devel::MODULE. For example, -d:DProf executes the script using the Devel::DProf profiler. See also the debugging section in Chapter 20, "The Perl Debugger".

-DLETTERS
-DNUMBER

Sets debugging flags. (This only works if debugging is compiled into your version of Perl as described below.) You may specify either a NUMBER that is the sum of the bits you want, or a list of LETTERS. To see how it executes your script, for instance, use -D14 or -Dslt. Another useful value is -D1024 or -Dx, which lists your compiled syntax tree. And -D512 or -Dr displays compiled regular expressions. The numeric value is available internally as the special variable $^D. Table 19-1 lists the assigned bit values.

Table 19.1. -D Options

Bit Letter Meaning
1 p Tokenizing and parsing
2 s Stack snapshots
4 l Label stack processing
8 t Trace execution
16 o Method and overloading resolution
32 c String/numeric conversions
64 P Print preprocessor command for -P
128 m Memory allocation
256 f Format processing
512 r Regex parsing and execution
1024 x Syntax tree dump
2048 u Tainting checks
4096 L Memory leaks (needs -DLEAKTEST when compiling Perl)
8192 H Hash dump--usurps values()
16384 X Scratchpad allocation
32768 D Cleaning up
65536 S Thread synchronization

All these flags require a Perl executable that was specially built for debugging. However, because this is not the default, you won't be able to use the -D switch at all unless you or your sysadmin built this special debugging version of Perl. See the INSTALL file in the Perl source directory for details, but the short story is that you need to pass -DDEBUGGING to your C compiler when compiling Perl itself. This flag is automatically set if you include the -g option when Configure asks you about optimizer and debugger flags.

If you're just trying to get a printout of each line of Perl code as it executes (the way that sh -x provides for shell scripts), you can't use Perl's -D switch. Instead do this:

# Bourne shell syntax
$ PERLDB_OPTS="NonStop=1 AutoTrace=1 frame=2" perl -dS program

# csh syntax
% (setenv PERLDB_OPTS "NonStop=1 AutoTrace=1 frame=2"; perl -dS program)
See Chapter 20, "The Perl Debugger" for details and variations.

-e PERLCODE

May be used to enter one or more lines of script. If -e is used, Perl will not look for the program's filename in the argument list. The PERLCODE argument is treated as if it ended with a newline, so multiple -e commands may be given to build up a multiline program. (Make sure to use semicolons where you would in a normal program stored in a file.) Just because -e supplies a newline on each argument doesn't imply that you must use multiple -e switches; if your shell supports multiline quoting like sh, ksh, or bash, you may pass a multiline script as one -e argument:

$ perl -e 'print "Howdy, ";
           print "@ARGV!\n";' world
Howdy, world!
With csh it's probably better to use multiple -e switches:
% perl -e 'print "Howdy, ";' \
       -e 'print "@ARGV!\n";' world
Howdy, world!
Both implicit and explicit newlines count in the line numbering, so the second print is on line 2 of the -e script in either case.

-FPATTERN

Specifies the pattern to split on when autosplitting via the -a switch (has no effect otherwise). The pattern may be surrounded by slashes (//), double quotes (""), or single quotes (''). Otherwise, it will be automatically put in single quotes. Remember that to pass quotes through a shell, you'll have to quote your quotes, and how you can do that depends on the shell.

-h

Prints a summary of Perl's command-line options.

-iEXTENSION
-i

Specifies that files processed by the <> construct are to be edited in place. It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for calls to print, printf, and write.[4]

[4]Technically, this isn't really "in place". It's the same filename, but a different physical file.

The EXTENSION is used to modify the name of the old file to make a backup copy. If no EXTENSION is supplied, no backup is made and the current file is overwritten. If the EXTENSION doesn't contain a *, then that string is appended to the end of the current filename. If the EXTENSION does contain one or more * characters, then each * is replaced by the filename currently being processed. In Perl terms, you could think of this as:

($backup = $extension) =~ s/\*/$file_name/g;
This allows you to use a prefix for the backup file, instead of--or even in addition to--a suffix:
% perl -pi'orig_*' -e 's/foo/bar/' xyx     # backup to 'orig_xyx'
You can even put backup copies of the original files into another directory (provided that the directory already exists):
% perl -pi'old/*.orig' -e 's/foo/bar/' xyx # backup to 'old/xyx.orig'
These pairs of one-liners are equivalent:
% perl -pi -e 's/foo/bar/' xyx             # overwrite current file
% perl -pi'*' -e 's/foo/bar/' xyx          # overwrite current file

% perl -pi'.orig' -e 's/foo/bar/' xyx      # backup to 'xyx.orig'
% perl -pi'*.orig' -e 's/foo/bar/' xyx     # backup to 'xyx.orig'
From the shell, saying:
% perl -p -i.orig -e "s/foo/bar/;"
is the same as using the program:
#!/usr/bin/perl -pi.orig
s/foo/bar/;
which is convenient shorthand for the remarkably longer:
#!/usr/bin/perl
$extension = '.orig';
LINE: while (<>) {
    if ($ARGV ne $oldargv) {
        if ($extension !~ /\*/) {
            $backup = $ARGV . $extension;
        }
        else {
            ($backup = $extension) =~ s/\*/$ARGV/g;
        }
        unless (rename($ARGV, $backup)) {
            warn "cannot rename $ARGV to $backup: $!\n";
            close ARGV;
            next;
        } 
        open(ARGVOUT, ">$ARGV");
        select(ARGVOUT);
        $oldargv = $ARGV;
    }
    s/foo/bar/;
}
continue {
    print;  # this prints to original filename
}
select(STDOUT);
This long code is virtually identical to the simple one-liner with the -i switch, except that the -i form doesn't need to compare $ARGV to $oldargv to know when the filename has changed. It does, however, use ARGVOUT for the selected filehandle and restore the old STDOUT as the default output filehandle after the loop. Like the code above, Perl creates the backup file irrespective of whether any output has truly changed. See the description of the eof function for examples of how to use use eof without parentheses to locate the end of each input file, in case you want to append to each file or to reset line numbering.

If, for a given file, Perl is unable to create the backup file as specified in the EXTENSION, it will issue a warning to that effect and continue processing any other remaining files listed.

You cannot use -i to create directories or to strip extensions from files. Nor can you use it with a ~ to indicate a home directory--which is just as well, since some folks like to use that character for their backup files:

% perl -pi~ -e 's/foo/bar/' file1 file2 file3...
Finally, the -i switch does not stop Perl from running if no filenames are given on the command line. When this happens, no backup is made since the original file cannot be determined, and processing proceeds from STDIN to STDOUT as might be expected.

-IDIRECTORY

Directories specified by -I are prepended to @INC, which holds the search path for modules. -I also tells the C preprocessor where to search for include files. The C preprocessor is invoked with -P; by default it searches /usr/include and /usr/lib/perl. Unless you're going to be using the C preprocessor (and almost no one does any more), you're better off using the use lib directive within your script. Like use lib, however, the -I switch implicitly adds platform-specific directories. See use lib in Chapter 31, "Pragmatic Modules", for details.

-lOCTNUM
-l

Enables automatic line-end processing. It has two effects: first, it automatically chomps the line terminator when used with -n or -p, and second, it sets $\ to the value of OCTNUM so that any print statements will have a line terminator of ASCII value OCTNUM added back on. If OCTNUM is omitted, -l sets $\ to the current value of $/, typically newline. So, to trim lines to 80 columns, say this:

% perl -lpe 'substr($_, 80) = ""'
Note that the assignment $\ = $/ is done when the switch is processed, so the input record separator can be different from the output record separator if the -l switch is followed by a -0 switch:
% gnufind / -print0 | perl -ln0e 'print "found $_" if -p'
This sets $\ to newline and later sets $/ to the null character. (Note that 0 would have been interpreted as part of the -l switch had it followed the -l directly. That's why we bundled the -n switch between them.)

-m and -M

These switches load a MODULE as if you'd executed a use, unless you specify -MODULE instead of MODULE, in which case they invoke no. For example, -Mstrict is like use strict, while -M-strict is like no strict.

-mMODULE

Executes useMODULE() before executing your script.

-MMODULE
-M'MODULE ...'

Executes useMODULE before executing your script. The command is formed by mere interpolation of the rest of the argument after the -M, so you can use quotes to add extra code after the module name, for example, -M'MODULE qw(foo bar)'.

-MMODULE=arg1,arg2...

A little built-in syntactic sugar means you can also say -Mmodule=foo,bar as a shortcut for -M'module qw(foo bar)'. This avoids the need to use quotes when importing symbols. The actual code generated by -Mmodule=foo,bar is:

use module split(/,/, q{foo,bar})
Note that the = form removes the distinction between -m and -M, but it's better to use the uppercase form to avoid confusion.

You may only use the -M and -m switches from a real command-line invocation of Perl, not as options picked up on the #! line. (Hey, if you're gonna put it in the file, why not just write the equivalent use or no instead?)

-n

Causes Perl to assume the following loop around your script, which makes it iterate over filename arguments much as sed -n or awk do:

LINE:
while (<>) {
    ...                # your script goes here
}
You may use LINE as a loop label from within you script, even though you can't see the actual label in your file.

Note that the lines are not printed by default. See -p to have lines printed. Here is an efficient way to delete all files older than a week:

find . -mtime +7 -print | perl -nle unlink
This is faster than using the -exec switch of find(1) because you don't have to start a process on every filename found. By an amazing coincidence, BEGIN and END blocks may be used to capture control before or after the implicit loop, just as in awk.

-p

Causes Perl to assume the following loop around your script, which makes it iterate over filename arguments much as sed does:

LINE:
while (<>) {
    ...         # your script goes here
}
continue {
    print or die "-p destination: $!\n";
}
You may use LINE as a loop label from within you script, even though you can't see the actual label in your file.

If a file named by an argument cannot be opened for some reason, Perl warns you about it, and moves on to the next file. Note that the lines are printed automatically. An error occurring during printing is treated as fatal. By yet another amazing coincidence, BEGIN and END blocks may be used to capture control before or after the implicit loop, just as in awk.

-P

Causes your script to be run through the C preprocessor before compilation by Perl. (Since both comments and cpp(1) directives begin with the # character, you should avoid starting comments with any words recognized by the C preprocessor such as "if", "else" or "define".) Whether you use -P switch or not, Perl still pays attention to #line directives to control the line number and filename, so any preprocessor can apprise Perl of these things. See the section Section 19.5.2, "Generating Perl in Other Languages" in Chapter 24, "Common Practices".

-s

Enables rudimentary switch-parsing for switches on the command line after the script name but before any filename arguments or a "--" switch-processing terminator. Any switch found is removed from @ARGV, and a variable by the same name as the switch is set in Perl. Switch bundling is not allowed because multicharacter switches are permitted.

The following script prints "true" only when the script is invoked with a -foo switch.

#!/usr/bin/perl -s
if ($foo) { print "true\n" }
If the switch is of the form -xxx=yyy, the $xxx variable is set to whatever follows the equals sign in that argument ("yyy" in this case). The following script prints "true" if and only if the script is invoked with a -foo=bar switch.
#!/usr/bin/perl -s
if ($foo eq 'bar') { print "true\n" }

-S

Makes Perl use the PATH environment variable to search for the script (unless the name of the script contains directory separators).

Typically, this switch is used to help emulate #! startup on platforms that don't support #!. On many platforms that have a shell compatible with Bourne or C shell, you can use this:

#!/usr/bin/perl
eval "exec /usr/bin/perl -S $0 $*"
        if $running_under_some_shell;
The system ignores the first line and feeds the script to /bin/sh, which proceeds to try to execute the Perl script as a shell script. The shell executes the second line as a normal shell command, and thus starts up the Perl interpreter. On some systems, $0 doesn't always contain the full pathname, so -S tells Perl to search for the script if necessary. After Perl locates the script, it parses the lines and ignores them because the variable $running_under_some_shell is never true. A better construct than $* would be ${1+"$@"}, which handles embedded spaces and such in the filenames but doesn't work if the script is being interpreted by csh. In order to start up sh instead of csh, some systems have to replace the #! line with a line containing just a colon, which Perl will politely ignore. Other systems can't control that and need a totally devious construct that will work under any of csh, sh, or perl, such as the following:
eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    & eval 'exec /usr/bin/perl -S $0 $argv:q'
                   if 0;
Yes, it's ugly, but so are the systems that work[5] this way.

[5] We use the term advisedly.

On some platforms, the -S switch also makes Perl append suffixes to the filename while searching for it. For example, on Win32 platforms, the .bat and .cmd suffixes are appended if a lookup for the original name fails and the name does not already end in one of those suffixes. If your Perl was built with debugging enabled, you can use Perl's -Dp switch to watch how the search progresses.

If the filename supplied contains directory separators (even as just a relative pathname, not an absolute one), and if the file is not found, those platforms that implicitly append file extensions (not Unix) will do so and look for the file with those extensions added, one by one.

On DOS-like platforms, if the script does not contain directory separators, it will first be searched for in the current directory before being searched for in the PATH. On Unix platforms, the script will be searched for strictly on the PATH, due to security concerns about accidentally executing something in the current working directory without explicitly requesting this.

-T

Forces "taint" checks to be turned on so you can test them. Ordinarily these checks are done only when running setuid or setgid. It's a good idea to turn them on explicitly for programs run on another's behalf, such as CGI programs. See Chapter 23, "Security".

Note that, for security reasons, Perl must see this option quite early; usually this means it must appear early on the command line or in the #! line. If it's not early enough, Perl complains.

-u

Causes Perl to dump core after compiling your script. You can then in theory take this core dump and turn it into an executable file by using the undump program (not supplied). This speeds startup at the expense of some disk space (which you can minimize by stripping the executable). If you want to execute a portion of your script before dumping, use Perl's dump operator instead. Note: availability of undump is platform specific; it may not be available for a specific port of Perl. It has been superseded by the new Perl-to-C code generator, which is much more portable (but still experimental).

-U

Allows Perl to do unsafe operations. Currently the only "unsafe" operations are unlinking directories while running as superuser, and running setuid programs with fatal taint checks turned into warnings. Note that warnings must be enabled to actually produce the taint-check warnings.

-v

Prints the version and patch level of your Perl executable, along with a bit of extra information.

-V

Prints a summary of the major Perl configuration values and the current value of @INC.

-V:NAME

Prints to STDOUT the value of the named configuration variable. The NAME may contain regex characters, like "." to match any character, or ".*" to match any optional sequence of characters.

% perl -V:man.dir
man1dir='/usr/local/man/man1'
man3dir='/usr/local/man/man3'

% perl -V:'.*threads'
d_oldpthreads='undef'
use5005threads='define'
useithreads='undef'
usethreads='define'
If you ask for a configuration variable that doesn't exist, its value will be reported as "UNKNOWN". Configuration information is available from within a program using the Config module, although patterns are not supported for the hash subscripts:
% perl -MConfig -le 'print $Config{man1dir}'
/usr/local/man/man1
See the Config module in Chapter 32, "Standard Modules".

-w

Prints warnings about variables that are mentioned only once and scalar values that are used before being set. Also warns about redefined subroutines, and references to undefined filehandles or filehandles opened read-only that you are attempting to write on. Also warns you if you use values as numbers that don't look like numbers, if you use an array as though it were a scalar, if your subroutines recurse more than 100 deep, and innumerable other things. See every entry labelled "(W)" in Chapter 33, "Diagnostic Messages".

This switch just sets the global $^W variable. It has no effect on lexical warnings--see the -W and -X switches for that. You can enable or disable specific warnings via the use warnings pragma, described in Chapter 31, "Pragmatic Modules".

-W

Unconditionally and permanently enables all warnings throughout the program, even if warnings were disabled locally using no warnings or $^W = 0. This includes all files loaded via use, require, or do. Think of it as the Perl equivalent of the lint(1) command.

-xDIRECTORY
-x

Tells Perl to extract a script that is embedded in a message. Leading garbage will be discarded until the first line that starts with #! and contains the string "perl". Any meaningful switches on that line after the word "perl" will be applied. If a directory name is specified, Perl will switch to that directory before running the script. The -x switch controls the disposal of leading garbage only, not trailing garbage. The script must be terminated with __END__ or __DATA__ if there is trailing garbage to be ignored. (The script can process any or all of the trailing garbage via the DATA filehandle if desired. It could even in theory seek to the beginning of the file and process the leading garbage.)

-X

Unconditionally and permanently disables all warnings, the exact opposite of what the -W flag does.



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.