LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2214 min read

Command-Line Arguments

Learn how to read arguments passed to a Perl script via @ARGV, and how to access the script name with $0.

Introduction

Command-line scripts are far more useful when they can accept input directly from whoever runs them, instead of having every value hard-coded. Perl makes this simple with the special array @ARGV, which automatically holds every argument typed after the script name on the command line.

What You Will Learn
  • What @ARGV is and how Perl populates it.
  • How to read individual command-line arguments.
  • How to loop over all arguments and parse simple flags.
  • What $0 holds and how it differs from @ARGV.

What Is @ARGV?

@ARGV is a built-in array that Perl automatically fills with every command-line argument passed after the script's filename, in order, as plain strings. Unlike in some languages, @ARGV does NOT include the script name itself — that is stored separately in $0.

use strict;
use warnings;
print "Number of arguments: ", scalar(@ARGV), "\n";
print "All arguments: @ARGV\n";
Running: perl greet.pl Alice 30

Click Run to see what this code prints.

Reading Positional Arguments

Because @ARGV is a normal array, you can access individual arguments by index, just like any other array. It is good practice to check that the expected number of arguments was actually provided before using them.

use strict;
use warnings;
if (@ARGV < 2) {
die "Usage: perl greet.pl <name> <age>\n";
}
my $name = $ARGV[0];
my $age = $ARGV[1];
print "Hello, $name! You are $age years old.\n";
Running: perl greet.pl Alice 30

Click Run to see what this code prints.

Using @ARGV in Boolean Context

if (@ARGV < 2) uses @ARGV in numeric context, which automatically evaluates to the number of elements it contains — a common, idiomatic Perl shortcut for checking argument count.

Looping Over @ARGV

When a script accepts a variable number of arguments — for example, a list of filenames to process — loop over @ARGV directly with foreach, exactly as you would with any other array.

use strict;
use warnings;
if (@ARGV == 0) {
die "Usage: perl total.pl <num1> <num2> ...\n";
}
my $total = 0;
foreach my $number (@ARGV) {
$total += $number;
}
print "Sum of arguments: $total\n";
Running: perl total.pl 10 20 30

Click Run to see what this code prints.

Simple Flag Parsing

Many command-line tools accept flags like --verbose or -n 5. For simple cases, you can parse @ARGV manually with shift and a loop. For anything more elaborate, the core module Getopt::Long handles this far more robustly.

use strict;
use warnings;
my $verbose = 0;
my @files;
while (@ARGV) {
my $arg = shift @ARGV;
if ($arg eq '--verbose') {
$verbose = 1;
} else {
push @files, $arg;
}
}
print "Verbose mode: ", ($verbose ? "on" : "off"), "\n";
print "Files to process: @files\n";
Running: perl process.pl --verbose report.txt data.csv

Click Run to see what this code prints.

Reach for Getopt::Long

For anything beyond a couple of simple flags, use the core module Getopt::Long, which handles --name=value pairs, short/long option aliases, and type validation for you: use Getopt::Long; GetOptions("verbose" => \$verbose);

The $0 Variable

$0 holds the name (and often the path) the script was invoked with. It is useful for printing usage messages that reference the script's own name, without hard-coding it, since that name might change if the file gets renamed or moved.

use strict;
use warnings;
print "This script is: $0\n";
print "Usage: perl $0 <name> <age>\n" if @ARGV < 2;
Running: perl greet.pl

Click Run to see what this code prints.

Common Mistakes

Avoid These Mistakes
  • Assuming @ARGV includes the script name itself — it does not; that is $0.
  • Forgetting to validate the number of arguments before accessing $ARGV[0], $ARGV[1], etc., risking undef values.
  • Treating command-line arguments as numbers without validation — they always arrive as plain strings.
  • Writing brittle, manual flag-parsing logic for a tool with many options instead of using Getopt::Long.
  • Modifying @ARGV while also expecting <> (the diamond operator) to still read from files named in it, without understanding that <> consumes @ARGV as filenames.

Best Practices

  • Always check @ARGV's length and die with a clear usage message if required arguments are missing.
  • Use Getopt::Long once a script needs more than one or two optional flags.
  • Document expected arguments in a comment or usage message near the top of the script.
  • Use $0 in usage/help text so it stays accurate even if the script file is renamed.
  • Validate that numeric arguments actually look like numbers before using them in calculations.

Frequently Asked Questions

@ARGV holds the arguments explicitly passed on the command line when the script was run. %ENV is a separate hash holding the process's environment variables, like $ENV{PATH} or $ENV{HOME}.

Yes — inside the main script body, shift with no arguments defaults to operating on @ARGV, so shift and shift(@ARGV) are equivalent there.

Use the diamond operator <STDIN> to read a line typed by the user while the script is running, which is different from @ARGV (arguments supplied when the script starts).

Yes, exactly as typed on the command line. Perl will automatically treat them as numbers when used in numeric context, but they are stored as strings.

Key Takeaways

  • @ARGV automatically holds every argument passed after the script name on the command line.
  • Access individual arguments by index ($ARGV[0]) or loop over all of them with foreach.
  • shift with no arguments defaults to shifting off @ARGV inside the main script.
  • Getopt::Long is the standard tool for parsing more complex flags and options.
  • $0 holds the script's own invoked name, separate from @ARGV.

Summary

Command-line arguments turn a hard-coded script into a flexible, reusable tool. Next, you will learn how to extend Perl even further using modules — both the ones that ship with Perl and the vast library of third-party code available through CPAN.

Next Lesson →

Modules & CPAN