使用Rust在PATH中查找可执行文件

bal*_*drs 4 rust

在Python中,我可以:

from distutils import spawn

cmd = spawn.find_executable("commandname")
Run Code Online (Sandbox Code Playgroud)

我尝试了类似下面的代码,但它假定您使用的是具有/usr/bin/which可用的类Unix系统(也涉及到要避免的外部命令的执行):

use std::process::Command;

let output = Command::new("which")
                      .arg("commandname")
                      .unwrap_or_else(|e| /* handle error here */)
Run Code Online (Sandbox Code Playgroud)

在Rust中最简单的方法是什么?

Aan*_*hen 9

我找到了一个解决问题的板条箱:which. 它包括 Windows 支持,甚至考虑到PATHEXT.


She*_*ter 5

我可能会抓住环境变量并对其进行遍历,返回第一个匹配路径:

use std::env;
use std::path::{Path, PathBuf};

fn find_it<P>(exe_name: P) -> Option<PathBuf>
    where P: AsRef<Path>,
{
    env::var_os("PATH").and_then(|paths| {
        env::split_paths(&paths).filter_map(|dir| {
            let full_path = dir.join(&exe_name);
            if full_path.is_file() {
                Some(full_path)
            } else {
                None
            }
        }).next()
    })
}

fn main() {
    println!("{:?}", find_it("cat"));
    println!("{:?}", find_it("dog"));
}
Run Code Online (Sandbox Code Playgroud)

在Windows上,这可能很难看,因为您必须将追加.exe到可执行文件名称上。还应该将其扩展为仅返回可执行的项目,这也是平台特定的代码。

回顾Python实现,看来它们也支持传递绝对路径。函数是否支持该功能取决于您。

快速搜索crates.io返回了一个可能有用的板条箱:quale,尽管它目前说

当前仅在类似Unix的操作系统上工作。

我发现还有其他人也就不足为奇了。


.exe如果缺少某些丑陋的代码,这些代码会添加到最后,但仅限Windows上。

#[cfg(not(target_os = "windows"))]
fn enhance_exe_name(exe_name: &Path) -> Cow<Path> {
    exe_name.into()
}

#[cfg(target_os = "windows")]
fn enhance_exe_name(exe_name: &Path) -> Cow<Path> {
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    let raw_input: Vec<_> = exe_name.as_os_str().encode_wide().collect();
    let raw_extension: Vec<_> = OsStr::new(".exe").encode_wide().collect();

    if raw_input.ends_with(&raw_extension) {
        exe_name.into()
    } else {
        let mut with_exe = exe_name.as_os_str().to_owned();
        with_exe.push(".exe");
        PathBuf::from(with_exe).into()
    }
}

// At the top of the `find_it` function:
// let exe_name = enhance_exe_name(exe_name.as_ref());
Run Code Online (Sandbox Code Playgroud)

  • 盲目使用`.exe` 不是*真正* 正确的。您应该使用 `PATHEXT` 环境变量,它是一个以 `;` 分隔的被视为“可执行”的文件扩展名列表。遗憾的是,您必须小心,因为 `CreateProcess`(这是 Rust 的 `Command` 类型所支持的,AFAIK)仅支持本机可执行类型,因此它不能像在 UNIX 上那样使用(*eg* 调用shell 脚本)。所以,除非你还打算使用 `ShellExecute`(Rust 不使用我不知道为什么)来编写你自己的代码,你应该限制自己使用 `.COM;.EXE`。 (2认同)