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."
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:
-
Specified line by line via -e
switches on the command line. For
example:
% perl -e "print 'Hello, World.'"
Hello, World.
-
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.
-
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.
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.
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]
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.
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.
| | |
18.7. Avant-Garde Compiler, Retro Interpreter | | 19.2. Environment Variables |
Copyright © 2001 O'Reilly & Associates. All rights reserved.
|