The issue you're encountering is due to how the shell interprets the command string. When you use std::process::Command::new(prog), it does not invoke a shell by default. This means environment variables like $USER are not expanded, and the command is treated literally.
echo $USER is passed as-is to the echo command, so $USER is not expanded to your username.bash or zsh) is responsible for expanding environment variables, but std::process::Command does not use a shell by default.sh -c to invoke a shellYou can explicitly invoke a shell (e.g., /bin/sh) and pass your command as a string to be interpreted by the shell:
rustfn main() { let command = "echo $USER"; let output = std::process::Command::new("/bin/sh") .arg("-c") .arg(command) .output() .unwrap(); println!("stdout: {}|", String::from_utf8_lossy(&output.stdout)); }
If you know the variable name, you can expand it manually using Rust's std::env module:
rustfn main() { let user = std::env::var("USER").unwrap_or_else(|_| "unknown".to_string()); println!("stdout: {}|", user); }
shell-words crate (for complex commands)If you need to split a command string into arguments safely, you can use the shell-words crate, but this still won't expand environment variables. You'd still need a shell for that.
For your use case, Solution 1 (sh -c) is the simplest and most direct way to get the expected behavior. It ensures the command is interpreted by a shell, allowing environment variable expansion.