2

I want to create a std::process::Command and check whether an executable actually exists at that location before actually spawning the Command later. What would be the pragmatic way to do this?

I have this code:

let c = std::process::Command::new("my_exe");
// something here
c.spawn().unwrap();

I want to be able to validate the my_exe path when creating the Command and then spawn way later.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ditoslav
  • 4,563
  • 10
  • 47
  • 79
  • What is "that location"? When you are telling for example your shell to run some program it is searched in paths specified in `$PATH`. Do you wish to manually check this paths and see if there is an executable with given name? – Aleksander Krauze Oct 10 '22 at 14:38
  • Yeah but I don't want to do $PATH manipulation to try out all the locations. Can this be done without external dependencies and just by using some function which does this for me? – ditoslav Oct 10 '22 at 14:40
  • "I don't want to do $PATH manipulation to try out all the locations." That's what happens under the hood anyway. – the8472 Oct 10 '22 at 16:59
  • I know that's what's happening under the hood but I would expect there is an already existing standard library call which does this for me – ditoslav Oct 11 '22 at 10:09

3 Answers3

7

check whether an executable actually exists at that location before actually spawning the Command.

Don't as that's a time-of-check to time-of-use race condition. Instead, check the error value from executing the Command: Check if a command is in PATH/executable as process.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
-2

If you want to check if a file is present in the working directory, you can use Path::exists, as described in How to check whether a path exists?.

Also, Command::spawn() takes a mutable reference to self so c needs to be mutable.

use std::path::Path;
use std::process::Command;

if Path::new("PATH_TO_EXECUTABLE").exists() {
    let mut c = Command::new("PATH_TO_EXECUTABLE");
    // do something
    c.spawn().unwrap();
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Loading
  • 426
  • 1
  • 5
  • 11
  • 1
    This doesn't handle the case of using an executable based on the `PATH`. See also [Finding executable in PATH with Rust](https://stackoverflow.com/q/37498864/155423) – Shepmaster Oct 10 '22 at 14:50
-3

Use the is_executable crate:

use is_executable::IsExecutable;
use std::fs;

let paths = fs::read_dir("./").unwrap();

for path in paths {
    let file_path = path.unwrap().path();
    if file_path.is_executable() {
        println!("File: {:?} is executable!", file_path);
    } else {
        println!("File: {:?} is _not_ executable!", file_path);
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Michał Hanusek
  • 199
  • 3
  • 13