command line arguments
command line parsing
argument processing
software development
programming tips

How can I read and process parse command line arguments?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Command line arguments let users pass options and data to a program at launch. Every language provides access to raw arguments as a string array, but most also have a dedicated parsing library that handles flags, options, help text, and validation. Python uses argparse, Node.js uses commander or yargs, Go uses flag, and Rust uses clap. Using a parsing library is almost always better than manually splitting argv.

Python (argparse)

python
1import argparse
2
3parser = argparse.ArgumentParser(description="Process some data")
4parser.add_argument("input", help="Input file path")
5parser.add_argument("-o", "--output", default="result.txt", help="Output file path")
6parser.add_argument("-n", "--count", type=int, default=10, help="Number of items")
7parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output")
8
9args = parser.parse_args()
10print(f"Input: {args.input}")
11print(f"Output: {args.output}")
12print(f"Count: {args.count}")
13print(f"Verbose: {args.verbose}")
bash
1$ python script.py data.csv -o output.txt -n 50 -v
2Input: data.csv
3Output: output.txt
4Count: 50
5Verbose: True
6
7$ python script.py --help
8usage: script.py [-h] [-o OUTPUT] [-n COUNT] [-v] input

For simple scripts, sys.argv gives raw access:

python
import sys
print(sys.argv)  # ['script.py', 'arg1', 'arg2']
print(sys.argv[1])  # 'arg1'

Node.js (process.argv and commander)

Raw access:

javascript
1// process.argv includes node path and script path
2console.log(process.argv);
3// ['/usr/bin/node', '/path/to/script.js', 'arg1', 'arg2']
4
5const args = process.argv.slice(2); // User arguments only
6console.log(args); // ['arg1', 'arg2']

Using commander:

javascript
1import { program } from 'commander';
2
3program
4  .argument('<input>', 'input file path')
5  .option('-o, --output <path>', 'output file', 'result.txt')
6  .option('-n, --count <number>', 'number of items', parseInt, 10)
7  .option('-v, --verbose', 'enable verbose output')
8  .parse();
9
10const options = program.opts();
11const input = program.args[0];
12console.log(`Input: ${input}`);
13console.log(`Output: ${options.output}`);
14console.log(`Count: ${options.count}`);
bash
$ node script.js data.csv -o output.txt -n 50 -v

Go (flag package)

go
1package main
2
3import (
4    "flag"
5    "fmt"
6)
7
8func main() {
9    output := flag.String("output", "result.txt", "Output file path")
10    count := flag.Int("count", 10, "Number of items")
11    verbose := flag.Bool("verbose", false, "Enable verbose output")
12    flag.Parse()
13
14    // Positional arguments (after flags)
15    args := flag.Args()
16    if len(args) < 1 {
17        fmt.Println("Usage: program [flags] <input>")
18        return
19    }
20
21    fmt.Printf("Input: %s\n", args[0])
22    fmt.Printf("Output: %s\n", *output)
23    fmt.Printf("Count: %d\n", *count)
24    fmt.Printf("Verbose: %v\n", *verbose)
25}
bash
$ go run main.go -output out.txt -count 50 -verbose data.csv

Rust (clap)

rust
1use clap::Parser;
2
3#[derive(Parser)]
4#[command(about = "Process some data")]
5struct Args {
6    /// Input file path
7    input: String,
8
9    /// Output file path
10    #[arg(short, long, default_value = "result.txt")]
11    output: String,
12
13    /// Number of items
14    #[arg(short = 'n', long, default_value_t = 10)]
15    count: u32,
16
17    /// Enable verbose output
18    #[arg(short, long)]
19    verbose: bool,
20}
21
22fn main() {
23    let args = Args::parse();
24    println!("Input: {}", args.input);
25    println!("Output: {}", args.output);
26    println!("Count: {}", args.count);
27    println!("Verbose: {}", args.verbose);
28}

Java

java
1public class Main {
2    public static void main(String[] args) {
3        // Raw access
4        for (int i = 0; i < args.length; i++) {
5            System.out.println("arg[" + i + "] = " + args[i]);
6        }
7
8        // Simple manual parsing
9        String input = args[0];
10        String output = "result.txt";
11        boolean verbose = false;
12
13        for (int i = 1; i < args.length; i++) {
14            switch (args[i]) {
15                case "-o": output = args[++i]; break;
16                case "-v": verbose = true; break;
17            }
18        }
19    }
20}

For production Java applications, use Apache Commons CLI or picocli for proper argument parsing.

Bash

bash
1#!/bin/bash
2
3# Using getopts for short options
4while getopts "o:n:v" opt; do
5    case $opt in
6        o) output="$OPTARG" ;;
7        n) count="$OPTARG" ;;
8        v) verbose=true ;;
9        \?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
10    esac
11done
12shift $((OPTIND - 1))
13
14input="$1"
15echo "Input: $input"
16echo "Output: ${output:-result.txt}"
17echo "Count: ${count:-10}"
18echo "Verbose: ${verbose:-false}"
bash
$ ./script.sh -o output.txt -n 50 -v data.csv

Common Pitfalls

  • Manually parsing argv in complex CLIs: Splitting arguments by hand misses edge cases like quoted strings, = signs in values (--output=file.txt), combined short flags (-vn 50), and -- to stop flag parsing. Use a proper parsing library.
  • Forgetting that argv[0] is the program name: In most languages, argv[0] is the script or executable path, not the first user argument. User arguments start at index 1 (or 2 in Node.js, which includes the node binary path).
  • Not providing help text: Users expect --help to show usage information. Argument parsing libraries generate this automatically, but raw argv parsing does not. Always include a help option.
  • Type coercion errors: Command line arguments are always strings. Forgetting to parse "50" to an integer causes type errors or unexpected string concatenation. Use the parsing library's type parameter (type=int in argparse, parseInt in commander).
  • Not validating required arguments: If a required positional argument is missing, the program should print usage instructions and exit with a non-zero code, not crash with an index-out-of-bounds error.

Summary

  • Use argparse (Python), commander (Node.js), flag (Go), or clap (Rust) instead of manual parsing
  • Raw argv access is fine for simple scripts with 1-2 arguments
  • Libraries handle flag parsing, type conversion, default values, help text, and validation automatically
  • argv[0] is the program name — user arguments start at index 1
  • Always provide --help output for command line tools
  • Validate required arguments and print clear error messages for missing or invalid input

Course illustration
Course illustration

All Rights Reserved.