Options with Getopt::Long
| Parsing options | |
| Option types | |
| Positional arguments | |
| --help with Pod::Usage |
Parsing options
@ARGV holds everything the shell passed after the script name, but splitting it by hand gets old after the second flag. Getopt::Long ships with Perl and does the job properly.
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my %opt = (verbose => 0, output => "-");
GetOptions(
\%opt,
"verbose|v+",
"output|o=s",
) or die "usage: backup.pl [--verbose] [--output FILE]\n";
print "verbose: $opt{verbose}\n";
print "output: $opt{output}\n";
Each string describes one option: the name, optional aliases after a pipe, and a type suffix. The results land in the hash you passed by reference, so --verbose sets $opt{verbose}.
./backup.pl --verbose --output=log.txt
verbose: 1 output: log.txt
GetOptions returns false on a bad option and prints a warning of its own. Check the return value, otherwise a typo like --verbse silently does nothing.
Option types
The suffix after the option name decides what the user may write and what you receive. Four characters cover almost every command line tool:
GetOptions(
\%opt,
"verbose|v+", # counter: -v -v
"force!", # boolean, --force / --noforce
"output|o=s", # required string
"tag=s@", # repeatable string
"workers|j=i", # integer
);
A bare name is a flag. The plus sign makes a counter, so -vvv gives three when bundling is enabled. The exclamation mark adds a negated form, and the at sign collects repeated values into an array reference.
Options accept both --output log.txt and --output=log.txt. Single letters also work with one dash: -o log.txt. To allow -vv as a bundle of single letters, configure it explicitly:
Getopt::Long::Configure("bundling");
Call Configure before GetOptions, once per program. Other useful settings are no_ignore_case to keep -v and -V distinct, and auto_abbrev to accept unique prefixes like --verb.
Positional arguments
Whatever is not an option stays in @ARGV, which is how you take file names after the flags. By default parsing stops at the first non-option word, so the rest is yours untouched:
my @files = @ARGV;
die "no input files\n" unless @files;
for my $file (@files) {
print "processing $file\n";
}
./backup.pl -v src/ lib/
processing src/ processing lib/
If you want flags to be recognised after file names too — backup.pl src/ --verbose — enable permutation. Use GetOptionsFromArray(\@args, \%opt, ...) when the words do not come from @ARGV, for example in a wrapper script that forwards arguments.
--help with Pod::Usage
A tool without --help is a tool nobody else can use. The clean way is to write the help text as POD at the bottom of the script and let Pod::Usage print it:
use Pod::Usage;
GetOptions(
\%opt,
"help|h" => sub { pod2usage(-exitval => 0, -verbose => 1) },
"verbose|v+",
"output|o=s",
) or pod2usage(-exitval => 2);
__END__
=head1 NAME
backup.pl - copy a folder into an archive
=head1 SYNOPSIS
backup.pl [--verbose] [--output FILE] DIR...
-verbose => 2 prints the full manual page instead of the synopsis. Setting -exitval => 2 on a parse failure is the convention that tells a calling script the arguments were wrong, as opposed to the work failing later.
./backup.pl --help
Usage: backup.pl [--verbose] [--output FILE] DIR...
Write the synopsis once and let it serve both the help screen and the manual page. Users read it, and so will you in six months.
Next: Environment and %ENV
Article author: Arthur Isaev