检查命令是否在PATH /可执行文件中作为进程

Luk*_*odt 7 rust

我想通过执行外部程序std::process::Command::spawn.此外,我想知道产生进程失败的原因:是因为给定的程序名不存在/不存在于PATH中还是因为某些不同的错误?

我想要实现的示例代码:

match Command::new("rustc").spawn() {
    Ok(_) => println!("Was spawned :)"),
    Err(e) => {
        if /* ??? */ {
            println!("`rustc` was not found! Check your PATH!")
        } else {
            println!("Some strange error occurred :(");
        }
    }, 
}
Run Code Online (Sandbox Code Playgroud)

当我尝试执行不在我的系统上的程序时,我得到:

Error { repr: Os { code: 2, message: "No such file or directory" } }
Run Code Online (Sandbox Code Playgroud)

但我不想依赖于此.有没有办法确定PATH中是否存在程序?

jki*_*ski 8

您可以使用它e.kind()来查找ErrorKind错误.

match Command::new("rustc").spawn() {
    Ok(_) => println!("Was spawned :)"),
    Err(e) => {
        if let NotFound = e.kind() {
            println!("`rustc` was not found! Check your PATH!")
        } else {
            println!("Some strange error occurred :(");
        }
    }, 
}
Run Code Online (Sandbox Code Playgroud)

编辑:我没有找到任何关于可以返回什么错误类型的明确文档,所以我查找了源代码.似乎错误是直接从操作系统返回的.相关代码似乎在src/libstd/sys/[unix/windows/..]/process.rs.来自Unix版本的片段:

还有一个编辑:再想一想,我不确定许可证是否真的允许在这里发布部分Rust源代码,所以你可以在github上看到它

哪只是回归Error::from_raw_os_err(...).Windows版本似乎更复杂,我无法立即找到它甚至返回错误的位置.无论哪种方式,您的操作系统似乎都受此限制.至少我发现了以下测试src/libstd/process.rs:

与上面相同:github

这似乎保证ErrorKind::NotFound至少应该在找不到二进制文件时返回.假设OS在其他情况下不会给出NotFound错误,但是谁知道,这是有意义的.如果你想绝对确定找不到程序,你必须手动搜索$ PATH中的目录.就像是:

use std::env;
use std::fs;

fn is_program_in_path(program: &str) -> bool {
    if let Ok(path) = env::var("PATH") {
        for p in path.split(":") {
            let p_str = format!("{}/{}", p, program);
            if fs::metadata(p_str).is_ok() {
                return true;
            }
        }
    }
    false
}

fn main() {
    let program = "rustca"; // shouldn't be found
    if is_program_in_path(program) {
        println!("Yes.");
    } else {
        println!("No.");
    }
}
Run Code Online (Sandbox Code Playgroud)