Rust Command-Line Arguments
Most of the small projects worth building as practice — a to-do list, a word counter — need to take input from the command line rather than hardcoding values in the source. This page covers the basics.
Reading arguments with std::env::args
Section titled “Reading arguments with std::env::args”use std::env;
fn main() { let args: Vec<String> = env::args().collect(); println!("{:?}", args);}If you compiled this into a program called greet and ran:
./greet AliceYou’d see:
["greet", "Alice"]The first element is always the program’s own name — the arguments you actually typed start at index 1.
Reading a specific argument
Section titled “Reading a specific argument”use std::env;
fn main() { let args: Vec<String> = env::args().collect();
if args.len() < 2 { println!("Usage: greet <name>"); return; }
let name = &args[1]; println!("Hello, {name}!");}Run with cargo run -- Alice and you’d get:
Hello, Alice!Run it with no arguments, and you’d see the usage message instead of a crash — checking args.len() before indexing avoids a panic if someone forgets to pass anything.
Parsing an argument into a number
Section titled “Parsing an argument into a number”Since every argument comes in as a String, you’ll often need .parse() (from the Type Casting page) to turn one into a number:
use std::env;
fn main() { let args: Vec<String> = env::args().collect();
if args.len() < 2 { println!("Usage: square <number>"); return; }
match args[1].parse::<i32>() { Ok(n) => println!("{}", n * n), Err(_) => println!("That's not a valid number"), }}For anything more than a couple of arguments: use clap
Section titled “For anything more than a couple of arguments: use clap”Manually indexing into args gets unwieldy fast once you need flags (--verbose), optional values, or helpful --help output. The standard solution is the clap crate, added with:
cargo add clap --features deriveuse clap::Parser;
#[derive(Parser)]struct Args { name: String,
#[arg(short, long, default_value_t = 1)] count: u32,}
fn main() { let args = Args::parse(); for _ in 0..args.count { println!("Hello, {}!", args.name); }}This gives you argument parsing, validation, and a working --help message, all generated from the struct definition. You don’t need clap for quick scripts, but for anything you’ll actually use more than once, it saves a lot of manual work.
std::env::args().collect()gives you aVec<String>of the command-line arguments; index 0 is always the program name.- Check
args.len()before indexing, so a missing argument doesn’t panic your program. .parse()turns aStringargument into a number, same as elsewhere.- For anything beyond a couple of plain arguments, the
clapcrate is the standard, well-worn choice.