use Getopt::Long; my $configfile; my @ARGVcopy = @ARGV; # because 1st pass eats all options in @ARGV!! { local $SIG{__WARN__} = sub { }; # don't complain when see options relevant to the 2nd pass Getopt::Long::GetOptions('--config=s', \$configfile); # no check! it will fail } die "config needed" unless $configfile; my $confighash = parse_configfile($configfile); # 2nd pass with restored ARGV @ARGV = @ARGVcopy; Getopt::Long::GetOptions( 'config=s' => \my $dummy, #<<<< this belongs to 1st phase but is still in cmdline (@ARGV) '--max-value=i' => \$confighash->{'a'}->{'b'}->{'max-value'}, ) or die "error cmd line params";