AtomicPorkchop
AtomicPorkchop

Reputation: 2675

Controlling arguments in perl with Getopt::Long

I am trying to use Getopt::Long add command line arguments to my script (seen below). The problem I am running into is related to multiple commands that do different things. For example I have an option flag that sets the configuration file to use with the script the option is -c [config_path] and I also have -h for help.

The problem I am running into is I need to have a condition that states whether or not the config option has been used AND a config file has been specified. I tried counting the options in @ARGV but found if -h and -c are specifed it causes the script to move on the to the subroutine load_config anyway. Because as seen in the code below when 2 arguments are found in @ARGV it fires the subroutine.

In what way could I fix this? At least in my head specifying -h and -c at the same time sorta contradicts each other. Is there a way to make it so only "informational commands" like help cannot be executed with "operational commands" like -c? Heck is there a way where I get a list of the commands that have been passed? I tried printing the contents of @ARGV but nothing was in it even though I had specified command arguments.

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use Term::ANSIColor;
use XML::Simple;
use Net::Ping;
use Net::OpenSSH;
use Data::Dumper;

# Create a new hash to copy XML::Simple configuration file data into
my %config_file;

# Clear the screen and diplay version information
system ("clear");
print "Solignis's Backup script v0.8 for ESX\\ESX(i) 4.0+\n";
print "Type -h or --help for options\n\n";

# Create a new XML::Simple object
my $xml_obj = XML::Simple->new();

# Create a new Net::Ping object
my $ping_obj = Net::Ping->new();

my $config_file;

my $argcnt = $#ARGV + 1;

GetOptions('h|help' => \&help, 
       'c|config=s' => \$config_file
      );

if ($argcnt == 0) {
    print "You must supply a config to be used\n";
} elsif ($argcnt == 2) {
    if (! -e $config_file) {
        print color 'red';
        print "Configuration file not found!\n";
        print color 'reset';
        print "\n";
        die "Script Halted\n";
    } else {
        load_config();
    }
}

sub load_config {

    print color 'green';
    print "$config_file loaded\n";
    print color 'reset';

    my $xml_file = $xml_obj->XMLin("$config_file",
                    SuppressEmpty => 1);

    foreach my $key (keys %$xml_file) {
            $config_file{$key} = $xml_file->{$key};
    }

    print Dumper (\%config_file);
}

sub help {
    print "Usage: backup.pl -c [config file]\n";
}

Upvotes: 2

Views: 2268

Answers (4)

Anomie
Anomie

Reputation: 94794

@ARGV is altered by GetOptions, that is why it seems empty. Rather than counting arguments, just directly check if $config_file is defined.

BTW, IMO there is no need to try to exclude -c from being used with -h. Normally a "help" just prints the help text and exits without taking any other action, check that first and it shouldn't matter whether -c is supplied or not.

Upvotes: 8

Martin Ellison
Martin Ellison

Reputation: 1343

You can always set a default value for the options eg my $help = 0; my $config_file = ""; and then test for those values.

Upvotes: 0

Jim Brandt
Jim Brandt

Reputation: 601

You might also want to check out Getopt::Euclid which presents some expanded ways to provide options and a cool way of using the programs documentation as the spec for the command-line arguments.

Upvotes: 0

Dre
Dre

Reputation: 4329

Something like

my $help;
my $config_file;

GetOptions('h|help' => \$help, 
   'c|config=s' => \$config_file
  );

if ( defined $help ) {
   help();
} elsif ( defined $config_file ) {
   ...;
} else {
   die "No arguments!";
}

Upvotes: 3

Related Questions