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

时间:2016-05-28 12:15:12

标签: rust

在Python中我可以:

from distutils import spawn

cmd = spawn.find_executable("commandname")

我尝试过类似下面代码的内容,但它假设您使用的是类似unix的系统,/usr/bin/which可用(还涉及执行我想避免的外部命令):

use std::process::Command;

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

在Rust中执行此操作的最简单方法是什么?

2 个答案:

答案 0 :(得分: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"));
}

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

回顾Python implementation,它们似乎也支持传递的绝对路径。如果该功能应该支持,那将由您决定。

快速搜索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());

答案 1 :(得分:1)

我找到了一个可以解决问题的板条箱:which。它包括Windows支持,甚至占PATHEXT