如何在没有目录部分的情况下获取当前程序的名称?

时间:2016-04-25 18:15:44

标签: rust

在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。)

3 个答案:

答案 0 :(得分:8)

如果你不关心为什么你无法获得程序名称,那么你可以通过明智地混合documentationmap来处理所有潜在的错误。另外,返回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)
    }
}

try it out on the Playground

答案 2 :(得分:0)

再增加一个Option版本:)

fn prog() -> Option<String> {
    std::env::current_exe()
        .ok()?
        .file_name()?
        .to_str()?
        .to_owned()
        .into()
}