NAME
CLI::Cmdline - Minimal command-line parser with short/long options and aliases in pure Perl
VERSION
1.22
SYNOPSIS
use CLI::Cmdline qw(parse);
my $switches = '-v -q -h|help --dry-run';
my $options = 'input --output --config --include';
# only define options which have no default value 0 or '';
my %opt = (
v => 1, # switch, will be incremented on each occurrence
include => [], # multiple values allowed
config => '/etc/myapp.conf',
);
CLI::Cmdline::parse(\%opt, $switches, $options)
or die "Usage: $0 [options] <files...>\nTry '$0 --help' for more information.\n";
# @ARGV now contains only positional arguments
die " .... " if $#ARGV < 0 || $ARGV[0] ne 'file.txt';
DESCRIPTION
Tiny, zero-dependency command-line parser supporting short/long options, aliases, bundling, repeated switches, array collection, and -- termination.
Short options:
-v,-vh,-headerLong options:
--verbose,--helpLong options with argument:
--output file.txtor--output=file.txtAliases via
|Optional leading
-or--in specification stringsSingle-letter bundling:
-vh,-vvv,-vd dirSwitches counted on repeat
Options collect into array only if default is ARRAY ref
--ends processingOn error: returns 0, restores @ARGV
On success: returns 1
EXAMPLES
Minimal example – switches without explicit defaults
You do not need to pre-define every switch with a default value. Missing switches are automatically initialized to 0.
my %opt;
parse(\%opt, '-v -h -x')
or die "usage: $0 [-v] [-h] [-x] files...\n";
# After parsing ./script.pl -vvvx file.txt
# %opt will contain: (v => 3, h => 0, x => 1)
# @ARGV == ('file.txt')
Required Options
To make an option required, declare it with an empty string default and check afterward:
my %opt = ( mode => 'normal');
parse(\%opt, '', '--input --output --mode')
or die "usage: $0 --input=FILE [--output=FILE] [--mode=TYPE] files...\n";
die "Error: --input is required\n" if ($opt{input} eq '');
Collecting multiple values, no default array needed
If you want multiple occurrences but don't want to pre-set an array:
my %opt = (
define => [], # explicitly an array ref
);
parse(\%opt, '', '--define')
or die "usage: $0 [--define NAME=VAL ...] files...\n";
# ./script.pl --define DEBUG=1 --define TEST --define PROFILE
# $opt{define} == ['DEBUG=1', 'TEST', 'PROFILE']
# Alternative: omit the default entirely (parser will not auto-create array)
# If you forget the [] default, repeated --define will overwrite the last value.
Realistic full script with clear usage message
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper $Data::Dumper::Sortkeys = 1;
use CLI::Cmdline qw(parse);
my $switches = '-v|verbose -q|quiet --help --dry-run -force|f';
my $options = '-input|i -output -mode -tag';
my %opt = ( v => 1, mode => 'normal', tag => [] ); # tag = multiple tags allowed
CLI::Cmdline::parse(\%opt, $switches, $options)
or die "Try '$0 --help' for more information. ARGV = @ARGV\n";
# --- check if ARGV is filled or help is required
Usage() if $#ARGV < 0 || $opt{help};
die "Error: --input is required. See $0 --help for usage.\n" if ($opt{input} eq '');
my $verbose = $opt{v} - $opt{q};
print "Starting processing (verbose $verbose)...\n" if $verbose > 0;
print Dumper(\%opt);
print "ARG = [".join('] [',@ARGV)."]\n";
exit 0;
sub Usage {
print <<"USAGE";
Usage : $0 [options] --input=FILE [files...]
Options:
-v|verbose Increase verbosity (repeatable)
-q|quiet Suppress normal output
--dry-run Show what would be done
-f|force Force operation even if risky
--input=FILE Input file (required)
--output=FILE Output file (optional)
--mode=MODE Processing mode, default: $opt{mode}
--tag=TAG Add a tag (multiple allowed)
--help Show this help message
Example:
$0 --input=data.csv -vvv file1.txt
$0 --input=data.csv --tag=2026 --tag=final -vv file1.txt
$0 --input=data.csv -quiet file1.txt
$0 -input=data.csv -dry-run file1.txt # not a long tag with =
$0 -input data.csv -vf file1.txt
$0 -vfi data.csv file1.txt
$0 -vif data.csv file1.txt # option not at the end
$0 file1.txt # missing input error
$0 --help
USAGE
exit 1;
}
Using -- to pass filenames starting with dash
my %opt;
parse(\%opt, '-r')
or die "usage: $0 [-r] files...\n";
# Command line:
./script.pl -r -- -hidden-file.txt another-file
# Results:
# $opt{r} == 1
# @ARGV == ('-hidden-file.txt', 'another-file')
AUTHOR
Hans Harder <hans@atbas.org>
LICENSE
This module is free software.
You can redistribute it and/or modify it under the same terms as Perl itself.
See the official Perl licensing terms: https://dev.perl.org/licenses/