Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Getopt::Long

Old News
;-)

Perl options processing

Recommended Books Recommended Links

 Perl for Unix System Administrators

Perl Reference

Perl Language

Perl Xref Debugging regular expressions   Perl Style Regular expressions Perl Programming Environment Pipes
Debugging Software Testing Program understanding Pretty Printing Perl Tips Humor Etc

The Free Software Foundation, when they were developing the GNU project, decided that single-letter
flags weren't friendly enough, so they invented 'long' flags. These use a double minus sign followed by a
word. To give a value, you'd say something like --language=french .

Getopt::Long provides the GetOptions() function which provides sophisicated parsing of command line including but not limited to the capability of handle long options. It provides support for:

Additional controls include: 

 Recipe 15.1 in the Perl Cookbook shows how to use these. The basic idea is as follows:
        use Getopt::Long;

        die "Usage: $0 [-b] [-user name]\n" unless @ARGV;

        my( $binary, $username );

        GetOptions( "b"       => \$binary,
                    "user=s"  => \$username );
      

Let's convert the above program to GNU options:


#!/usr/bin/perl
# hellolong.plx
# Hello World (Deluxe) - with long flags
use warnings;
use strict;
use Getopt::Long;
my %options;
GetOptions(%options, "language:s", "help", "version");
if ($options{version}) {
print "Hello World, version 3.n";
exit;
} elsif ($options{help}) {
print <<EOF;
$0: Typical Hello World program
Syntax: $0 [–-help|--version|--language=<language>]
--help : This help message
--version : Print version on standard output and exit
--language : Turn on international language support.
EOF
exit;
} elsif ($options{language}) {
if ($options{language} eq "french") {
print "Bonjour, tout le monde.n";
} else {
die "$0: unsupported languagen";
}
} else {
print "Hello, world.n";
}

 

We can still use the previous syntax, but now we can also say:

> perl hellolong.plx --language=french

Bonjour, tout le monde.


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Nov 17, 2010] Parsing the Command Line with Getopt::*

Programs need input, and for many programs, input begins on the command line. For example, a program to print files might be invoked as
pr -l -n -a 10:00 foo bar
pr is the name of the program; it is followed here by six arguments. The arguments are of two sorts: options and file names.

-l, -n, and -a 10:00 are options. They control the manner in which the program executes. In this case, -l tells pr to print in landscape orientation, -n tells it to print page numbers, and -a 10:00 tells it to print after 10:00. Options are sometimes called options or switches. foo and bar are file names. pr will read these files to obtain the actual text to print.

Parsing the Command Line

In Perl, command line arguments are made available to the program in the global @ARGV array. This happens automatically: you don't have to declare anything or do anything to get them. If you wrote pr in Perl and entered the command line shown above, then at the beginning of program execution @ARGV would have six elements:
$ARGV[0]	'-l'
$ARGV[1]	'-n'
$ARGV[2]	'-a'
$ARGV[3]	'10:00'
$ARGV[4]	'foo'
$ARGV[5]	'bar'
Now the fun starts. Given @ARGV as shown, the program has to identify -l, -n, and -a as options, associate 10:00 with -a, and identify foo and bar as file names. This is called parsing the command line.

Easy to be Hard.

Parsing the command line is a problem. The problem isn't that it is so hard, but rather that it is so easy: for many programs, it can be done in under 20 lines of code. Because parsing the command line seems easy, it is often not identified as a distinct function of the program. It never gets a functional specification, or a design, or even the considered attention of the programmer. This leads to many bad things:

The Eightfold Path

In Perl, there is a better way. In fact, there are many better ways. In 00modlist.long.html, we find
Getopt::Declare      An easy-to-use WYSIWYG command-line parser
Getopt::EvaP         Long/short options, multilevel help          
Getopt::Long         Advanced option handling                     
Getopt::Mixed        Supports both long and short options         
Getopt::Regex        Option handling using regular expressions    
Getopt::Simple       A simplified interface to Getopt::Long       
Getopt::Std          Implements basic getopt and getopts          
Getopt::Tabular      Table-driven argument parsing with help text 
Each of these is a Perl module for parsing the command line. They have been designed, written, debugged, and encapsulated. You don't have to write them again. They support standard interfaces.

Getopt::Std

If the list above seems daunting, start with Getopt::Std. Getopt::Std supports a good, simple command line style that is adequate for many programs. It automatically handles options given in any of these forms:
pr -l -n -a 10:30 foo bar
pr -lna 10:30 foo bar
pr -lna10:30 foo bar
To use Getopt::Std, write
use Getopt::Std;
my %Options;
getopt('a', \%Options);
Getopt::Std exports the getopt() routine. getopt() takes two parameters: a string and a hash reference. The string lists all the options that take arguments. The hash receives the options found on the command line.

getopt() removes the options from @ARGV and parses them. Upon return, each option appears as a hash key in %Options. For each key, the hash value is the argument of the option if it takes one, and 1 if it does not. Finally, any file names that follow the options are left in @ARGV for the program to process. For any of the command lines shown above, getopt() would set %Options and @ARGV to

%Options = (l => 1,
            n => 1,
            a => '10:30')

@ARGV    = qw(foo bar)
Getopt::Std also has another interface:
$ok = getopts('a:ln', \%Options);
Like getopt(), getopts() takes a string and a hash reference. The string includes all the option letters: both those that take arguments and those that do not. Option letters that take an argument are marked with a trailing colon. Because getopts() has a list of all the valid options, it can do some simple error checking: getopts() returns false if there are invalid options on the command line, and true otherwise.

Getopt::Long

If you need more power that Getopt::Std provides, consider using Getopt::Long. The name ::Long refers to an option style that uses two dashes and the complete option name, rather than a single character:
pr --landscape --numbers --after 10:30 foo bar
However, Getopt::Long is not merely Getopt::Std with a facelift. It provides a large-some would say bewildering-assortment of facilities for parsing the command line in different ways. In addition, Getopt::Long has evolved over the last ten years, reflecting changes in the underlying Perl language, changes in programming style, and changes in interface style. At the same time, it maintains backward compatibility with previous versions.

All this makes the programming interface to Getopt::Long large and complex. For a complete description, you should read the documentation that is contained within the module itself. Here, I'll give just a brief survey, illustrating the simpler features, and reflecting current style.

Basic Facilities

Conceptually, the interface to Getopt::Long is similar to that of Getopt::Std. It exports a routine named GetOptions(). GetOptions() takes a series of option specifiers, which tell it how to parse the command line, and a hash reference, where it stores the results. It returns true if there are no errors.
$ok = GetOptions(\%Options, "landscape", "numbers!", "after=s");
Each option specifier gives the name of an option, possibly followed by an argument specifier. The name will become a hash key. The argument specifier tells how to parse the argument to that option.

In the example above, landscape has no argument specifier. This means that it takes no argument, and $Options{landscape} will be 1 or 0 according as --landscape does or does not appear on the command line. numbers! also takes no argument, but the ! means that it may be explicitly negated by prefixing it with no on the command line:

pr --nonumbers
after=s takes a string argument; the argument will become the value of $Options{after}. after:s also takes a string argument, but the colon means that the argument is optional. Other argument specifiers are =i for integer arguments and =f for floating point arguments.

A double dash on the command line terminates the option list.

Hairy Stuff

If an argument specifier is suffixed with an @, then the option may be given multiple times on the command line, and the corresponding value in %Options becomes a reference to an array containing all the values supplied for that option. For example:
GetOptions(\%Options, "x=f@", "y=f@")
will parse
graph --x 1 --x 2 --x 3 --y 1 --y 4 --y 9
resulting in
%Options = (x => [1, 2, 3],
            y => [1, 4, 9])
Similarly, if an argument specifier is suffixed with a %, then the option takes key=value pairs, and the corresponding value in %Options becomes a reference to a hash of those pairs. So
GetOptions(\%Options, "define=s%")
will parse Stroustrup's example
cc --define sqrt=rand --define exit=abort hello.cc
resulting in
%Options = (define => { sqrt => 'rand',
                        exit => 'abort' })

The Kitchen Sink

The empty string is a valid option. It is written on the command line as a single dash, and results in the null key being entered into %Options with a value of 1. This form is conventionally used to specify that the program should take input from STDIN, rather than from a named file:
cat - 
You don't have to store all the options in %Options. Each option can have its own linkage specification, which may be a scalar ref, an array ref, a hash ref, or a code ref. For scalar, array, and hash refs, the option is stored in the referenced variable. If the linkage specification is a code ref, the option isn't stored anywhere; instead, the option name and value are passed to the referenced subroutine.

Option names can have aliases, and can be abbreviated to uniqueness. You can configure Getopt::Long for compatibility with GNU, or POSIX. You can control case sensitivity. You can cluster options. You can pass options through to called programs. You can intersperse options and non-option arguments on the command line. This allows different files to be processed with different options:

pr --numbers foo --nonumbers bar
Finally, you can specify a code ref to process arguments that aren't options. This allows GetOptions() to process the entire command line, and potentially reduces your program to a single
GetOptions(...);
call, plus subroutines.

The Rest of the Pack

Getopt::Std and Getopt::Long are both supplied with the standard Perl distribution. There are currently six other Getopt:: modules available on CPAN. Here is a quick tour.

Getopt::Simple

Getopt::Simple describes itself as a simple wrapper around Getopt::Long. However, nothing that supports the functionality of Getopt::Long can be entirely simple. In fact, Getopt::Simple is an object-oriented wrapper around Getopt::Long. Rather than coding option descriptions into strings, Getopt::Simple lays them out in hash tables:
$descriptions = { landscape => { type => ''   },
		  numbers   => { type => ''   },
		  after	    => { type => '=s' }  }
getOptions() is invoked as a method on a Getopt::Simple object:
$options = new Getopt::Simple;
$options->getOptions($descriptions, 
		     "Usage: pr -landscape -numbers -after time");
and options are retrieved through the $options object:
$option->{switch}{landscape} and ...
$option->{switch}{after    } and ...

Getopt::Tabular

Getopt::Tabular uses a table to describe options, and then parses the command line through a procedural interface:
@options = (['-landscape', 'boolean', 0, \$landscape',
		'print in landscape orientation'],
			 
	    ['-numbers'  , 'boolean', 0, \$numbers'  ,
		'print page numbers'		],
			
	    ['-after'    , 'string' , 1, \$time'     ,
		 'print after time'		],      );
         
GetOptions(\@options, \@ARGV) or exit 1;
Each line in the table describes a single option, and specifies the option name, type, number of arguments, action to take, and help text. The simplest action is to set a scalar; Getopt::Tabular can also collect arguments from the command line and assign them to an array, or pass them to a subroutine.

If anything goes wrong, GetOptions() automatically formats an error message, based on the help text supplied in @options. Getopt::Tabular also supplies an entry point called SpoofGetOptions().

SpoofGetOptions(\@options, \@ARGV)
parses the command line and checks it for errors, but doesn't take any action. This is particularly useful for programs that use subroutines to process arguments, because subroutines can do expensive or irreversible things.

Getopt::Mixed

Getopt::Mixed supports both long and short options: long because they are easy to remember; short because they are easy to type. Long options are introduced on the command line with two dashes; short options with one:
pr --landscape -a 12:00 foo bar
The programming interface is similar to Getopt::Long:
Getopt::Mixed::getOptions(@option_descriptions)
There is also an iterative form, which allows the program to process options one at a time:
Getopt::Mixed::init(@option_descriptions);
while (($option, $value) = Getopt::Mixed::nextOption()) { ... }
Getopt::Mixed::cleanup();
The results are stored in global variables. Given the command line shown above, Getopt::Mixed would set
$opt_landscape = 1
$opt_a         = '12:00'
Non-options arguments are left in @ARGV.

Getopt::Declare

Getopt::Declare doesn't parse anything directly. Rather, it builds and runs a parser. Options and their arguments are laid out in a single specification string:
$spec = q(-l		Print in landscape mode { $landscape = 1 }
	  -n		Print page numbers      { $numbers   = 1 }
	  -a <time:s>	Print after time	{ Queue($time)   });
The string describes each option, along with help text and a BLOCK to be executed when the option is found. Getopt::Declare::new creates a parser object from a specification string:
$parser = new Getopt::Declare $spec;
As written, this builds a parser and runs it on the command line; with additional arguments, it can parse strings or configuration files. Options and their values can be retrieved from $parser, but this is typically unnecessary, because the BLOCKs in the specification string contain arbitrary Perl code. There are powerful facilities for specifying and checking option syntax and arguments. Options can be required, and groups of options can be made mutually exclusive. Usage lines are automatically generated from the help text. The parser object can be saved and later run on different input.

Getopt::EvaP

Getopt::EvaP is broadly similar to Getopt::Simple and Getopt::Declare. Options and help text are specified in tables. A call to EvaP() parses the command line according to the tables and returns the results in an %Options hash:
EvaP \@option_specs, \@help_text, \%options
Perhaps the most interesting feature of Getopt::EvaP is that it has been implemented for Perl, Perl/Tk, Tcl and C. If you are developing in multiple languages, EvaP can provide a consistent user interface across all your applications.

Getopt::Regex

Getopt::Regex takes a different approach to managing the potential complexity of command line syntax. Rather than implementing sophisticated parsing facilities of its own, it relies on the Perl regular expression engine.
GetOptions(\@ARGV, [$regex, \$scalar  , $takesarg], 
  		   [$regex, sub {...} , $takesarg], ...);
For each option, the user passes an array ref. The first element is a regular expression, the second is either a scalar ref or a code ref, and the third indicates whether the option takes an argument. An element of @ARGV is recognized as an option if it matches a $regex. When an option is found, GetOptions() sets $scalar or calls sub {...}, as appropriate. If the option takes an argument, the argument is assigned to $scalar, or passed to sub {...}.

The Importance of Being Lazy

One of the principal virtues of a programmer is Laziness, and these modules provide a wonderful opportunity to be Lazy. Before parsing your own command line, look to see if there isn't a Getopt:: module that will do what you need. If there is, use it. If there isn't, encapsulate your parsing code in a new Getopt:: module, and consider submitting it to CPAN. Then other programmers can be Lazy, even if you can't.

[Mar 19, 2010] perl.com- Option and Configuration Processing Made Easy

Option and Configuration Processing Made Easy
By Jon Allen
July 12, 2007

When you first fire up your editor and start writing a program, it's tempting to hardcode any settings or configuration so you can focus on the real task of getting the thing working. But as soon as you have users, even if the user is only yourself, you can bet there will be things they want to choose for themselves.

A search on CPAN reveals almost 200 different modules dedicated to option processing and handling configuration files. By anyone's standards that's quite a lot, certainly too many to evaluate each one.

Luckily, you already have a great module right in front of you for handling options given on the command line: Getopt::Long, which is a core module included as standard with Perl. This lets you use the standard double-dash style of option names:

myscript --source-directory "/var/log/httpd" --verbose \ --username=JJ

Using Getopt::Long

When your program runs, any command-line arguments will be in the @ARGV array. Getopt::Long exports a function, GetOptions(), which processes @ARGV to do something useful with these arguments, such as set variables or run blocks of code. To allow specific option names, pass a list of option specifiers in the call to GetOptions() together with references to the variables in which you want the option values to be stored.

As an example, the following code defines two options, --run and --verbose. The call to GetOptions() will then assign the value 1 to the variables $run and $verbose respectively if the relevant option is present on the command line.

use Getopt::Long;
my ($run,$verbose);
GetOptions( 'run'     => \$run,
             'verbose' => \$verbose );

When Getopt::Long has finished processing options, any remaining arguments will remain in @ARGV for your script to handle (for example, specified filenames). If you use this example code and call your script as:

myscript --run --verbose file1 file2 file3

then after GetOptions() has been called the @ARGV array will contain the values file1, file2, and file3.

Types of Command-Line Options

The option specifier provided to GetOptions() controls not only the option name, but also the option type. Getopt::Long gives a lot of flexibility in the types of option you can use. It supports Boolean switches, incremental switches, options with single values, options with multiple values, and even options with hash values.

Some of the most common specifiers are:

name     # Presence of the option will set $name to 1
name!    # Allows negation, e.g. --name will set $name to 1,
         #    --noname will set $name to 0
name+    # Increments the variable each time the option is found, e.g.
         # if $name = 0 then --name --name --name will set $name to 3
name=s   # String value required
         #    --name JJ or --name=JJ will set $name to JJ
         # Spaces need to be quoted
         #    --name="Jon Allen" or --name "Jon Allen"

So, to create an option that requires a string value, format the call to GetOptions() like this:

my $name;
GetOptions( 'name=s' => \$name );

The value is required. If the user omits it, as in:

myscript --name

then the call to GetOptions() will die() with an appropriate error message.

Options with Multiple Values

The option specifier consists of four components: the option name; data type (Boolean, string, integer, etc.); whether to expect a single value, a list, or a hash; and the minimum and maximum number of values to accept. To require a list of string values, build up the option specifier:

Option name:   name
Option value:  =s    (string)
Option type:   @     (array)
Value counter: {1,}  (at least 1 value required, no upper limit)

Putting these all together gives:

my $name;
GetOptions('name=s@{1,}' => \$name);

Now invoking the script as:

myscript --name Barbie Brian Steve

will set $name to the array reference ['Barbie','Brian','Steve'].

Giving a hash value to an option is very similar. Replace @ with % and on the command line give arguments as key=value pairs:

my $name;
GetOptions('name=s%{1,}',\$name);

Running the script as:

myscript --name Barbie=Director JJ=Member

will store the hash reference { Barbie => 'Director', JJ => 'Member' } in $name.

Storing Options in a Hash

By passing a hash reference as the first argument to GetOptions, you can store the complete set of option values in a hash instead of defining a separate variable for each one.

my %options;
GetOptions( \%options, 'name=s', 'verbose' );

Option names will be hash keys, so you can refer to the name value as $options{name}. If an option is not present on the command line, then the corresponding hash key will not be present.

Options that Invoke Subroutines

A nice feature of Getopt::Long is that, as an alternative to simply setting a variable when an option is found, you can tell the module to run any code of your choosing. Instead of giving GetOptions() a variable reference to store the option value, pass either a subroutine reference or an anonymous code reference. This will then be executed if the relevant option is found.

GetOptions( version => sub{ print "This is myscript, version 0.01\n"; exit; }
            help    => \&display_help );

When used in this way, Getopt::Long also passes the option name and value as arguments to the subroutine:

GetOptions( name => sub{ my ($opt,$value) = @_; print "Hello, $value\n"; } );

You can still include code references in the call to GetOptions() even if you use a hash to store the option values:

my %options;
GetOptions( \%options, 'name=s', 'verbose', 'dest=s',
            'version' => sub{ print "This is myscript, version 0.01\n"; exit; } );

Dashes or Underscores?

If you need to have option names that contain multiple words, such as a setting for "Source directory," you have a few different ways to write them:

--source-directory
--source_directory
--sourcedirectory

To give a better user experience, Getopt::Long allows option aliases to allow either format. Define an alias by using the pipe character (|) in the option specifier:

my %options;
GetOptions( \%options, 'source_directory|source-directory|sourcedirectory=s' );

Note that if you're storing the option values in a hash, the first option name (in this case, source_directory) will be the hash key, even if your user gave an alias on the command line.

If you have a lot of options, it might be helpful to generate the aliases using a function:

use strict;
use warnings;
use Data::Dumper;
use Getopt::Long;

my %specifiers = ( 'source-directory' => '=s',
                   'verbose'          => '' );
my %options;
GetOptions( \%options, optionspec(%specifiers) );

print Dumper(\%options);

sub optionspec {
  my %option_specs = @_;
  my @getopt_list;

  while (my ($option_name,$spec) = each %option_specs) {
    (my $variable_name = $option_name) =~ tr/-/_/;
    (my $nospace_name  = $option_name) =~ s/-//g;
    my  $getopt_name   = ($variable_name ne $option_name)
        ? "$variable_name|$option_name|$nospace_name" : $option_name;

    push @getopt_list,"$getopt_name$spec";
  }

  return @getopt_list;
}

Running this script with each format in turn shows that they are all valid:

varos:~/writing/argvfile jj$ ./optionspec.pl --source-directory /var/spool
$VAR1 = {
          'source_directory' => '/var/spool'
        };

varos:~/writing/argvfile jj$ ./optionspec.pl --source_directory /var/spool
$VAR1 = {
          'source_directory' => '/var/spool'
        };

varos:~/writing/argvfile jj$ ./optionspec.pl --sourcedirectory /var/spool
$VAR1 = {
          'source_directory' => '/var/spool'
        };

Additionally, Getopt::Long is case-insensitive by default (for option names, not values), so your users can also use --SourceDirectory, --sourceDirectory, etc., as well:

varos:~/writing/argvfile jj$ ./optionspec.pl --SourceDirectory /var/spool
$VAR1 = {
          'source_directory' => '/var/spool'
        };

Configuration Files

The next stage on from command-line options is to let your users save their settings into config files. After all, if your program expands to have numerous options it's going to be a real pain to type them in every time.

When it comes to the format of a configuration file, there are a lot of choices, such as XML, INI files, and the Apache httpd.conf format. However, all of these formats share a couple of problems. First, your users now have two things to learn: the command-line options and the configuration file syntax. Second, even though many CPAN modules are available to parse the various config file formats, you still must write the code in your program to interact with your chosen module's API to set whatever variables you use internally to store user settings.

Getopt::ArgvFile to the Rescue

Fortunately, someone out there in CPAN-land has the answer (you can always count on the Perl community to come up with innovative solutions). Getopt::ArgvFile tackles both of these problems, simplifying the file format and the programming interface in one fell swoop.

To start with, the file format used by Getopt::ArgvFile is extremely easy for users to understand. Config settings are stored in a plain text file that holds exactly the same directives that a user would type on the command line. Instead of typing:

myscript --source-directory /usr/local/src --verbose --logval=alert

your user can use the config file:

--source-directory /usr/local/src
--verbose
--logval=alert

and then run myscript for instant user gratification with no steep learning curve.

Now to the clever part. Getopt::ArgvFile itself doesn't actually care about the contents of the config file. Instead, it makes it appear to your program that all the settings were actually options typed on the command line--the processing of which you've already covered with Getopt::Long. As well as saving your users time by not making them learn a new syntax, you've also saved yourself time by not needing to code against a different API.

The most straightforward method of using Getopt::ArgvFile involves simply including the module in a use statement:

use Getopt::ArgvFile home=>1;

A program called myscript that contains this code will search the user's home directory (whatever the environment variable HOME is set to) for a config file called .myscript and extract the contents ready for processing by Getopt::Long.

Here's a complete example:

use strict;
use warnings;
use Getopt::ArgvFile home=>1;
use Getopt::Long;

my %config;
GetOptions( \%config, 'name=s' );

if ($config{name}) {
  print "Hello, $config{name}\n";
} else {
  print "Who am I talking to?\n";
}

Save this as hello, then run the script with and without a command-line option:

varos:~/writing/argvfile jj$ ./hello
Who am I talking to?

varos:~/writing/argvfile jj$ ./hello --name JJ
Hello, JJ

Now, create a settings file called .hello in your home directory containing the --name option. Remember to double quote the value if you want to include spaces.

varos:~/writing/argvfile jj$ cat ~/.hello
--name "Jon Allen"

Running the script without any arguments on the command line will show that it loaded the config file, but you can also override the saved settings by giving the option on the command line as normal.

varos:~/writing/argvfile jj$ ./hello
Hello, Jon Allen

varos:~/writing/argvfile jj$ ./hello --name JJ
Hello, JJ

Advanced Usage

In many cases the default behaviour invoked by loading the module will be all you need, but Getopt::ArgvFile can also cater to more specific requirements.

User-Specified Config Files

Suppose your users want to save different sets of options and specify which one to use when they run your program. This is possible using the @ directive on the command line:

varos:~/writing/argvfile jj$ cat jj.conf
--name JJ

varos:~/writing/argvfile jj$ ./hello
Hello, Jon Allen

varos:~/writing/argvfile jj$ ./hello @jj.conf
Hello, JJ

Note that there's no extra programming required to use this feature; handling @ options is native to Getopt::ArgvFile.

Changing the Default Config Filename or Location

Depending on your target audience, the naming convention offered by Getopt::ArgvFile for config files might not be appropriate. Using a dotfile (.myscript) will render your user's config file invisible in his file manager or when listing files at the command prompt, so you may wish to use a name like myscript.conf instead.

Again, it may also be helpful to allow for default configuration files to appear somewhere other than the user's home directory, for example, if you need to allow system-wide configuration.

A further consideration here is PAR , the tool for creating standalone executables from Perl programs. PAR lets you include data files as well as Perl code, so you can bundle a default settings file using a command such as:

pp hello -o hello.exe -a hello.conf

which will be available to your script as $ENV{PAR_TEMP}/inc/hello.conf.

I mentioned earlier that Getopt::ArgvFile can load arbitrary config files if the filename appears with the @ directive on the command line. Essentially, what the module does when loaded with:

use Getopt::ArgvFile home=>1;

is to prepend @ARGV with @$ENV{HOME}/.scriptname, then resolve all @ directives, leaving @ARGV with the contents of the files. This means that running the script as:

myscript --name=JJ

is basically equivalent to writing:

myscript @$ENV{HOME}/.myscript --name-JJ

To load other config files, Getopt::ArgvFile supports disabling the automatic @ARGV processing and triggering it later. With a little manipulation of @ARGV first, you can make:

myscript --name=JJ

equivalent to:

myscript @/path/to/default.conf @/path/to/system.conf @/path/to/user.conf \
    --name=JJ

which will load the set of config files in the correct priority order.

All you need to do to enable this feature is change the use statement to read:

use Getopt::ArgvFile qw/argvFile/;

Loading the module in this way tells Getopt::ArgvFile to export the function argvFile(), which your program needs to call to process the @ directives, and also prevents any automated processing from occurring.

Here's an example that first loads a config file from the application bundle (if packaged by PAR) and then from the directory containing the application binary:

use File::Basename qw/basename/;
use FindBin qw/$Bin/;
use Getopt::ArgvFile qw/argvFile/;

# Define config filename as <application_name>.conf
(my $configfile = basename($0)) =~ s/^(.*?)(?:\..*)?$/$1.conf/;

# Include config file from the same directory as the application binary
if (-e "$Bin/$configfile") {
  unshift @ARGV,'@'."$Bin/$configfile";
}

# If we have been packaged with PAR, include the config file from the
# application bundle
if ($ENV{PAR_TEMP} and -e "$ENV{PAR_TEMP}/inc/$configfile") {
  unshift @ARGV,'@'."$ENV{PAR_TEMP}/inc/$configfile";
}

argvFile();  # Process @ARGV to load specified config files

You can also use this technique together with File::HomeDir to access the user's application data directory in a cross-platform manner, so that the location of the config file conforms to the conventions set by the user's operating system.

Summary

Getopt::Long provides an easy to use, extensible system for processing command-line options. With the addition of Getopt::ArgvFile, you can seamlessly handle configuration files with almost no extra coding. Together, these modules should be first on your list when writing scripts that need any amount of configuration.



Etc

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: March 12, 2019