在Bash中,这将是${0##*/}
。
use std::env;
use std::path::Path;
fn prog() -> String {
let prog = env::args().next().unwrap();
String::from(Path::new(&prog).file_name().unwrap().to_str().unwrap())
}
fn main() {
println!("{}", prog());
}
有更好的方法吗? (我特别不喜欢那些unwrap()
s。)
答案 0 :(得分:8)
如果你不关心为什么你无法获得程序名称,那么你可以通过明智地混合documentation和map
来处理所有潜在的错误。另外,返回Option
表示可能的失败:
use std::env;
use std::path::Path;
use std::ffi::OsStr;
fn prog() -> Option<String> {
env::args().next()
.as_ref()
.map(Path::new)
.and_then(Path::file_name)
.and_then(OsStr::to_str)
.map(String::from)
}
fn main() {
println!("{:?}", prog());
}
如果您想关注and_then
使用delnan's awesome suggestion(我刚学会了!),请将env::args().next()
替换为env::current_exe().ok()
。
如果你想知道为什么你不能获得程序名称(并且知道为什么通常是解决问题的第一步),那么请查看std::env::current_exe
。
答案 1 :(得分:4)
你也可以摆脱unwraps并仍然正确地报告所有错误原因(而不是将它们闯入&#34;失败的东西&#34; None
)。您甚至不需要指定转换方法的完整路径:
fn prog() -> Result<String, ProgError> {
let path = try!(env::current_exe());
let name = try!(path.file_name().ok_or(ProgError::NoFile));
let s_name = try!(name.to_str().ok_or(ProgError::NotUtf8));
Ok(s_name.to_owned())
}
与未来的问号运算符一起,这也可以写成单点调用链:
fn prog() -> Result<String, ProgError> {
Ok(env::current_exe()?
.file_name().ok_or(ProgError::NoFile)?
.to_str().ok_or(ProgError::NotUtf8)?
.to_owned())
}
当然,这具有ProgError
类型的先决条件:
use std::io::Error;
#[derive(Debug)]
enum ProgError {
NoFile,
NotUtf8,
Io(Error),
}
impl From<Error> for ProgError {
fn from(err: Error) -> ProgError {
ProgError::Io(err)
}
}
答案 2 :(得分:0)
再增加一个Option
版本:)
fn prog() -> Option<String> {
std::env::current_exe()
.ok()?
.file_name()?
.to_str()?
.to_owned()
.into()
}