Como passar e processar argumentos de linha de comando em Rust?
\n\nTodo mundo que já escreveu utilitários de console em Python sabe como é conveniente obter parâmetros através de sys.argv. Mas quando você migra para Rust — uma linguagem de programação de sistemas que promete velocidade e segurança — surge uma pergunta natural: "How can I access command line parameters in Rust?"
Esta pergunta é uma das mais populares no Stack Overflow (dezenas de milhares de visualizações), e não é à toa. Rust oferece não uma, mas três abordagens principais para trabalhar com argumentos de linha de comando. Desde o mais simples std::env::args() até bibliotecas poderosas como clap e structopt. Neste artigo, vamos analisar cada uma delas com exemplos práticos, para que você possa escolher a ferramenta adequada para sua tarefa.
Por que isso é importante?
\nSaber trabalhar com argumentos de linha de comando é uma habilidade básica para qualquer desenvolvedor Rust. Sem ela, não é possível criar:
\n- \n
- Utilitários CLI (por exemplo, um análogo do grep, find ou seu próprio script de deploy); \n
- Aplicações de servidor com configuração através de flags de inicialização; \n
- Ferramentas para automação e DevOps. \n
Vamos começar com a maneira mais simples e, em seguida, passar gradualmente para soluções profissionais.
\n\nMétodo 1: std::env::args() — abordagem minimalista
\n\nA maneira mais simples de obter argumentos de linha de comando em Rust é usar a função padrão std::env::args(). Ela retorna um iterador de strings, onde o primeiro elemento é o caminho para o arquivo executável e os demais são os parâmetros passados.
use std::env;\n\nfn main() {\n let args: Vec<String> = env::args().collect();\n \n // O primeiro argumento é sempre o nome do programa\n println!("Caminho para o programa: {}", args[0]);\n \n // Os demais são argumentos do usuário\n if args.len() > 1 {\n println!("Argumentos passados:");\n for (i, arg) in args[1..].iter().enumerate() {\n println!(" Argumento {}: {}", i + 1, arg);\n }\n } else {\n println!("Nenhum argumento passado.");\n }\n}\n\nVamos executar nosso programa:
\n$ cargo run -- hello world 42\nCaminho para o programa: ./target/debug/myapp\nArgumentos passados:\n Argumento 1: hello\n Argumento 2: world\n Argumento 3: 42\n\nVantagens: código mínimo, sem dependências, controle total.
\nDesvantagens: processamento manual de flags (por exemplo, --name ou -v), ausência de verificação de tipos (todos os argumentos são strings), sem ajuda embutida --help.
Este método é ideal para esboços rápidos ou quando você tem exatamente um argumento obrigatório. Mas para projetos sérios, vale a pena considerar alternativas.
\n\nVariante com env::args_os()
\nSe você precisar de bytes brutos (por exemplo, para trabalhar com nomes de arquivos não-UTF8), use std::env::args_os(). Ela retorna OsString em vez de String:
use std::env;\nuse std::ffi::OsString;\n\nfn main() {\n let args: Vec<OsString> = env::args_os().collect();\n println!("Primeiro argumento (OsString): {:?}", args[0]);\n}\n\nMétodo 2: Crate clap — parsing declarativo
\n\nQuando o projeto cresce, o parsing manual de argumentos se torna uma fonte de bugs. É aí que entra o clap — o crate mais popular para trabalhar com linha de comando no ecossistema Rust. Ele permite descrever declarativamente todos os parâmetros, flags e subcomandos.
\n\nAdicione ao Cargo.toml:
[dependencies]\nclap = { version = "4.5", features = ["derive"] }\n\nAgora, um exemplo usando derive-macros (método recomendado):
\n\nuse clap::Parser;\n\n/// Programa simples para demonstrar clap\n#[derive(