Perl command line arguments
last modified October 8, 2026
In this article we work with command line arguments, environment variables, exit codes and options in Perl.
Scripts receive their command line arguments in the @ARGV array,
the environment is exposed through the %ENV hash, and the script
name is stored in $0. For option parsing, the core module
Getopt::Long is available.
Perl @ARGV array
The first example prints the script name, the number of arguments, and the arguments themselves.
#!/usr/bin/perl use v5.34.0; use warnings; say "Script name: $0"; say "Number of arguments: ", scalar(@ARGV); say "Arguments: @ARGV";
Arguments are stored in @ARGV as strings, in the order they were
given. $0 holds the name of the script as it was invoked.
$ perl args.pl alpha beta "gamma delta" Script name: args.pl Number of arguments: 3 Arguments: alpha beta gamma delta
The quoted argument "gamma delta" is a single element of
@ARGV, even though it contains a space. The shell removes the
quotes before Perl sees the argument.
Perl shift in main program and in subroutines
The shift function removes the first element of an array. Without
an argument, it works on @ARGV at the top level of the program,
but on @_ inside a subroutine.
#!/usr/bin/perl
use v5.34.0;
use warnings;
sub inside_sub {
my $arg = shift;
say "Inside sub, shift returned: ", $arg // 'undef';
}
inside_sub();
say "ARGV still has: @ARGV";
my $first = shift;
say "Top-level shift returned: $first";
say "ARGV now has: @ARGV";
The subroutine is called without arguments, so its shift takes
from the empty @_ and returns undef. The
@ARGV array is not touched by that call.
my $first = shift;
At the top level, the same shift removes the first command line
argument from @ARGV.
$ perl shift.pl one two Inside sub, shift returned: undef ARGV still has: one two Top-level shift returned: one ARGV now has: two
Counting and iterating over arguments
In the next example, we count the arguments with scalar(@ARGV)
and loop over them by index and with foreach.
#!/usr/bin/perl
use v5.34.0;
use warnings;
my $count = scalar(@ARGV);
say "Got $count argument(s)";
for my $i (0 .. $#ARGV) {
say "Argument $i: $ARGV[$i]";
}
say "Iterating with foreach:";
foreach my $arg (@ARGV) {
say " $arg";
}
$#ARGV is the index of the last element, so 0 .. $#ARGV
covers every index. When there are no arguments, $#ARGV is -1 and
the loop body does not run.
$ perl count.pl red green blue Got 3 argument(s) Argument 0: red Argument 1: green Argument 2: blue Iterating with foreach: red green blue
Perl %ENV environment variables
The %ENV hash gives access to the environment variables of the
process. Reading a missing key returns undef, so we use the
defined-or operator // to provide a default.
#!/usr/bin/perl
use v5.34.0;
use warnings;
my $name = $ENV{GREETING_NAME} // 'Guest';
say "Hello, $name!";
say "GREETING_NAME is set: ", (exists $ENV{GREETING_NAME} ? 'yes' : 'no');
The program reads the GREETING_NAME variable. The exists
check tells us whether the variable is present at all.
$ perl env.pl Hello, Guest! GREETING_NAME is set: no $ GREETING_NAME=Alice perl env.pl Hello, Alice! GREETING_NAME is set: yes
In the second run, the shell sets the variable only for that single command.
Setting environment variables for child processes
Assigning to a key of %ENV changes the environment of the Perl
process. Any child process started afterwards, such as one created by
system, inherits the new value. The change does not affect the
shell that started the script.
#!/usr/bin/perl
use v5.34.0;
use warnings;
$| = 1;
$ENV{GREETING} = "Hello from Perl";
system('sh', '-c', 'echo "Child sees: $GREETING"');
say "Parent sees: $ENV{GREETING}";
We set GREETING in %ENV and then run a shell with
system. The single quotes stop Perl from interpolating
$GREETING, so the shell expands it instead. We set $|
to 1 so that the output of the parent and the child appears in the right order.
system('sh', '-c', 'echo "Child sees: $GREETING"');
The list form of system runs sh directly, without
going through an extra shell layer for Perl's quoting rules.
$ perl child.pl Child sees: Hello from Perl Parent sees: Hello from Perl
Perl exit codes
The exit function ends the program and returns a status code to the
caller. By convention, 0 means success and any non-zero value means failure.
This example validates its argument and uses different codes for different
problems.
#!/usr/bin/perl
use v5.34.0;
use warnings;
my $file = shift @ARGV;
unless (defined $file) {
say STDERR "Usage: $0 FILE";
exit 2;
}
if (-e $file) {
say "$file exists";
exit 0;
}
say STDERR "$file does not exist";
exit 1;
Messages for the user go to STDERR, and the status is set with
exit. Note that we use shift @ARGV explicitly here for
clarity.
my $file = shift @ARGV;
We take the first argument, or undef when no argument is given.
$ perl exit.pl Usage: exit.pl FILE $ echo $? 2 $ perl exit.pl missing.txt missing.txt does not exist $ echo $? 1
The shell variable $? holds the exit status of the last command.
Perl Getopt::Long
Getopt::Long is a core module that parses options such as
--verbose, --name=Alice or -c 3. Its
GetOptions function stores the values in variables that we pass
by reference. Each option specification ends with a type: no suffix for a
flag, =s for a string, and =i for an integer.
#!/usr/bin/perl
use v5.34.0;
use warnings;
use Getopt::Long;
my $verbose = 0;
my $name = 'World';
my $count = 1;
GetOptions(
'verbose|v' => \$verbose,
'name|n=s' => \$name,
'count|c=i' => \$count,
) or die "Error in command line arguments\n";
say "Verbose: ", $verbose ? 'yes' : 'no';
say "Name: $name";
say "Count: $count";
for (1 .. $count) {
say "Hello, $name!";
}
say "Remaining arguments: @ARGV" if @ARGV;
The verbose|v specification is a flag that is set to 1 when given.
The name|n=s and count|c=i options take a string and an
integer. The vertical bar gives a long and a short name. After
GetOptions removes the options it recognizes, the remaining
arguments stay in @ARGV.
) or die "Error in command line arguments\n";
GetOptions returns false when it finds an invalid option, so we
stop the program in that case.
$ perl options.pl --verbose --name=Alice -c 3 extra Verbose: yes Name: Alice Count: 3 Hello, Alice! Hello, Alice! Hello, Alice! Remaining arguments: extra $ perl options.pl Verbose: no Name: World Count: 1 Hello, World!
Getopt::Long with a hash of defaults
When GetOptions receives a hash reference as its first argument, it
stores each option value under its name in that hash. This keeps the defaults
and the parsed values in one place. The verbose|v! specification
also accepts --no-verbose.
#!/usr/bin/perl
use v5.34.0;
use warnings;
use Getopt::Long;
my %opt = (
name => 'World',
count => 1,
verbose => 0,
);
GetOptions(\%opt, 'name|n=s', 'count|c=i', 'verbose|v!')
or die "Error in command line arguments\n";
for my $key (sort keys %opt) {
say "$key: $opt{$key}";
}
The defaults are set before parsing. Any option given on the command line overwrites its default. Since the keys match the option names, we do not need separate variables.
$ perl hash.pl -c 2 -n Bob count: 2 name: Bob verbose: 0 $ perl hash.pl --no-verbose count: 1 name: World verbose: 0 $ perl hash.pl -v count: 1 name: World verbose: 1
In this article we have covered @ARGV, shift,
$0, %ENV, exit codes and Getopt::Long in
Perl.
Source
Author
List all Perl tutorials.