🎓 A1Learner
🔍
0 of 149 lessons completed

Rust Environment Variables

Environment variables are settings that live in the terminal itself. A program can read them.

Read one variable

env::var("NAME") returns a Result: Ok with the value as a String when the setting exists, Err when it does not. Run with MODE not set, this prints:

match env::var("MODE") {
    Ok(value) => println!("mode is {value}"),
    Err(_) => println!("MODE is not set"),
}

Give a missing variable a fallback

unwrap_or_else supplies a calm fallback instead of a panic. unwrap_or_default() does the same with the type's empty value:

let mode = env::var("MODE")
    .unwrap_or_else(|_| String::from("normal"));
println!("mode = {mode}");

Presence can be the whole switch

env::var("NAME").is_ok() is true when the variable is set to anything at all. Many tools turn a feature on exactly this way:

let ignore_case = env::var("IGNORE_CASE").is_ok();
println!("ignore_case = {ignore_case}");

Set one for a single run

Writing the variable before the command sets it for that run only. On Windows PowerShell, set it on its own line first:

IGNORE_CASE=1 cargo run -- to poem.txt

See them all, or keep odd values intact

std::env::vars() walks every variable the terminal passed to your program. A value might not be valid Unicode text. For that case, env::var_os("NAME") returns an Option<OsString> instead of a Result<String>. So no information is lost:

let raw = env::var_os("MODE");
println!("present = {}", raw.is_some());

Set a variable from inside the program

env::set_var sets a variable for this program and any children it starts afterwards. In edition 2024 this call is unsafe. Changing the environment while another thread reads it can clash. So set variables once, early in main:

env::set_var("MODE", "fast");
println!("mode = {}", env::var("MODE").unwrap());

Example

use std::env;
fn main() {
    let mode = env::var("MODE").unwrap_or_else(|_| String::from("normal"));
    let ignore_case = env::var("IGNORE_CASE").is_ok();
    println!("mode = {mode}");
    println!("ignore_case = {ignore_case}");
}

Key points

  • An environment variable is a named text setting in the terminal, like MODE or IGNORE_CASE, written in UPPER_CASE by habit
  • A program can change its behaviour from an environment variable without any new typing on each run.

In this example, the output shows a run where neither variable is set. env::var("MODE") returns Err, so unwrap_or_else steps in and supplies the fallback text normal. env::var("IGNORE_CASE") is also Err, so is_ok() is false. The program prints mode = normal and ignore_case = false. Run it as MODE=fast with IGNORE_CASE set to any value. The same code would print mode = fast and ignore_case = true. No code change. Just different settings.

Note

Arguments are typed fresh on every run.

An environment variable is set once.

It then applies to every run in that terminal session.

That is good for session-wide choices.

It is also easy to forget you set it.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

A tool should search case-insensitively whenever a variable named IGNORE_CASE is set to anything. Which check fits?