Skip to content

Reading Command-Line Arguments

Programs often need input.

Programs often need input.

One simple source of input is the command line.

When a program starts, the operating system passes a list of arguments to it. Zig can read these arguments through the standard library.

This program prints every argument:

const std = @import("std");

pub fn main() !void {
    var args = std.process.args();

    while (args.next()) |arg| {
        std.debug.print("{s}\n", .{arg});
    }
}

Run it:

zig run main.zig -- one two three

The output is:

zig-out/bin/main
one
two
three

The first line is usually the program name.

The remaining lines are the arguments typed after the program name.

The function signature is now different:

pub fn main() !void

Earlier programs returned void.

This program returns !void.

The ! means the function may return an error.

Reading arguments may fail, so the function must allow errors to propagate.

The line:

var args = std.process.args();

creates an argument iterator.

An iterator produces one value at a time.

Arguments are read with:

args.next()

next() returns an optional value.

If another argument exists, the result contains the argument.

If no argument remains, the result is null.

The loop:

while (args.next()) |arg| {
    ...
}

means:

  1. Call args.next()
  2. If the result contains a value, bind it to arg
  3. Run the loop body
  4. Repeat

The variable arg is a slice of bytes. In practice it behaves like a string.

Print it with {s}:

std.debug.print("{s}\n", .{arg});

A program can use arguments to control its behavior.

This version greets the first argument:

const std = @import("std");

pub fn main() !void {
    var args = std.process.args();

    _ = args.next();

    const name = args.next() orelse {
        std.debug.print("usage: hello NAME\n", .{});
        return;
    };

    std.debug.print("hello, {s}\n", .{name});
}

Run it:

zig run main.zig -- zig

The output is:

hello, zig

The line:

_ = args.next();

reads and ignores the program name.

_ means the value is intentionally discarded.

The expression:

args.next() orelse { ... }

means:

  1. Call args.next()
  2. If the result contains a value, use it
  3. Otherwise run the block after orelse

This is a common Zig pattern for handling optional values.

Programs become much more useful once they can read input. Command-line arguments are the simplest form of input, and they work everywhere Zig runs.

Exercise 1-21. Run the argument-printing program with different arguments.

Exercise 1-22. Modify the greeting program to print two names.

Exercise 1-23. Print the number of arguments passed to the program.

Exercise 1-24. Remove all command-line arguments and observe the output.