Check if the command is in the PATH / executable as a process

I want to execute an external program via std::process::Command::spawn . In addition, I want to know the reason why the spawning process failed: is it because the given program name does not exist / is not in the PATH or because of some error?

Example code that I want to achieve:

 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 :("); } }, } 

When I try to execute a program that is not included in my system, I get:

 Error { repr: Os { code: 2, message: "No such file or directory" } } 

But I do not want to rely on this. Is there a way to determine if a program exists in PATH?

+6
source share
1 answer

You can use e.kind() to find that ErrorKind error.

 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 :("); } }, } 

Edit: I did not find explicit documentation about what types of errors can be returned, so I looked at the source code. It seems that the error is returning directly from the OS. The corresponding code seems to be in src/libstd/sys/[unix/windows/..]/process.rs . Snippet from Unix version:

One more edit: with a second thought, I'm not sure if licenses really allow publishing parts of Rust sources here, so you can see them on github

What exactly returns Error::from_raw_os_err(...) . The Windows version seemed more complicated, and I could not immediately find where it even returned errors from. In any case, it seems that you are confident in your operating system. At least I found the following test in src/libstd/process.rs :

Same as above: github

It is like ErrorKind::NotFound should be returned, at least when the binary is not found. It makes sense to assume that the OS will not give a NotFound error in other cases, but who knows. If you want to be absolutely sure that the program is not really found, you will have to manually look for directories in $ PATH. Sort of:

 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."); } } 
+6
source

All Articles