如何检查路径中是否存在程序

时间:2009-06-01 09:52:38

标签: java scala runtime

我正在用scala编写一个程序,调用:

Runtime.getRuntime().exec( "svn ..." )

我想检查命令行中是否有“svn”(即可以在PATH中访问)。 我怎么能这样做?

PS:我的程序设计为在Windows上运行

9 个答案:

答案 0 :(得分:17)

也许有人会对Java 8解决方案感兴趣:

String exec = <executable name>;
boolean existsInPath = Stream.of(System.getenv("PATH").split(Pattern.quote(File.pathSeparator)))
        .map(Paths::get)
        .anyMatch(path -> Files.exists(path.resolve(exec)));

顺便说一句,您可以将anyMatch(...)替换为filter(...).findFirst() - 这样您就可以获得确切的可执行路径。

答案 1 :(得分:13)

我不是scala程序员,但我会用任何语言执行的操作是执行类似'svn help'之类的操作来检查exec方法的返回码(0或1)...如果它失败了svn不在路径中:P

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("svn help");
int exitVal = proc.exitValue();

按照惯例,值0表示正常终止。

答案 2 :(得分:4)

Selenium在类org.openqa.selenium.os.ExecutableFinder中具有相当完整的Windows / Linux / Mac实现,自{Selenium 3.1以来public访问{以前只能通过已弃用的方法访问org.openqa.selenium.os.CommandLine#find })。它虽然是ASL 2.0。

请注意,ExecutableFinder在Windows上无法理解PATHEXT - 它只有一组硬编码的可执行文件扩展名(.exe,.com,.bat)。

答案 3 :(得分:3)

此代码在Windows上使用“where”命令,在其他系统上使用“which”命令,以检查系统是否知道PATH中所需的程序。如果找到,则该函数将java.nio.file.Path返回给程序,否则返回null。

我在Windows 7和Linux Mint 17.3上使用Java 8进行了测试。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Logger;


public class SimulationUtils
{
    private final static Logger LOGGER = Logger.getLogger(SimulationUtils.class.getName());

    public static Path lookForProgramInPath(String desiredProgram) {
        ProcessBuilder pb = new ProcessBuilder(isWindows() ? "where" : "which", desiredProgram);
        Path foundProgram = null;
        try {
            Process proc = pb.start();
            int errCode = proc.waitFor();
            if (errCode == 0) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
                    foundProgram = Paths.get(reader.readLine());
                }
                LOGGER.info(desiredProgram + " has been found at : " + foundProgram);
            } else {
                LOGGER.warning(desiredProgram + " not in PATH");
            }
        } catch (IOException | InterruptedException ex) {
            LOGGER.warning("Something went wrong while searching for " + desiredProgram);
        }
        return foundProgram;
    }

    private static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }
}

使用它:

    System.out.println(SimulationUtils.lookForProgramInPath("notepad"));

在我的Windows 7系统上,它显示:

  

C:\ Windows \ System32下\ Notepad.exe的

在linux上:

    System.out.println(SimulationUtils.lookForProgramInPath("psql"));
  

的/ usr /斌/ PSQL

此方法的优点是它应该可以在任何平台上运行,并且不需要解析PATH环境变量或查看注册表。即使找到,也不会调用所需的程序。最后,没有必要知道程序扩展。 Windows下的gnuplot.exe和Linux下的gnuplot都可以通过相同的代码找到:

    SimulationUtils.lookForProgramInPath("gnuplot")

欢迎提出改进建议!

答案 4 :(得分:2)

关于原始问题,我也会检查FMF建议的存在。

我还想指出,您必须至少处理该过程的输出,读取可用数据,以便不会将流填充到边缘。否则会导致进程被阻塞。

为此,使用proc.getInputStream()(对于System.out)和proc.getErrorStream()(对于System.err)检索进程的InputStream,并读取不同线程中的可用数据。

我只是告诉你,因为这是一个常见的陷阱,而且svn可能会产生相当多的输出,所以请不要为了offtopic而投票;)

答案 5 :(得分:0)

如果你安装了cygwin,你可以先调用“which svn”,如果它在可执行路径中,它将返回svn的绝对路径,或者“which:no svn in(...)”。如果找不到,“which”的调用将返回exitValue为1,如果找到则返回0。您可以通过FMF详细信息的方式检查此错误代码。

答案 6 :(得分:0)

根据我的经验,通过调用带有ProcessBuilder的命令来判断各种系统是不可能的,如果它退出与否(Exceptions和返回值都不一致)

所以这是一个Java7解决方案,它遍历PATH环境变量并寻找匹配工具。将检查目录中的所有文件。 matchesExecutable必须是忽略扩展名和大小写的工具名称。

public static File checkAndGetFromPATHEnvVar(final String matchesExecutable) {
    String[] pathParts = System.getenv("PATH").split(File.pathSeparator);
    for (String pathPart : pathParts) {
        File pathFile = new File(pathPart);

        if (pathFile.isFile() && pathFile.getName().toLowerCase().contains(matchesExecutable)) {
            return pathFile;
        } else if (pathFile.isDirectory()) {
            File[] matchedFiles = pathFile.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return FileUtil.getFileNameWithoutExtension(pathname).toLowerCase().equals(matchesExecutable);
                }
            });

            if (matchedFiles != null) {
                for (File matchedFile : matchedFiles) {
                    if (FileUtil.canRunCmd(new String[]{matchedFile.getAbsolutePath()})) {
                        return matchedFile;
                    }
                }
            }
        }
    }
    return null;
}

以下是帮手:

public static String getFileNameWithoutExtension(File file) {
        String fileName = file.getName();
        int pos = fileName.lastIndexOf(".");
        if (pos > 0) {
            fileName = fileName.substring(0, pos);
        }
        return fileName;
}

public static boolean canRunCmd(String[] cmd) {
        try {
            ProcessBuilder pb = new ProcessBuilder(cmd);
            pb.redirectErrorStream(true);
            Process process = pb.start();
            try (BufferedReader inStreamReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                while ((inStreamReader.readLine()) != null) {
                }
            }
            process.waitFor();
        } catch (Exception e) {
            return false;
        }
        return true;
}

答案 7 :(得分:0)

这类似于Dmitry Ginzburg的答案,但是它也解决了在PATH环境变量中有人具有无效路径的罕见情况。这将导致InvalidPathException

private static final String ENVIRONMENT_VARIABLES_TEXT = System.getenv("PATH");

private static boolean isCommandAvailable(String executableFileName)
{
    String[] environmentVariables = ENVIRONMENT_VARIABLES_TEXT.split(File.pathSeparator);
    for (String environmentVariable : environmentVariables)
    {
        try
        {
            Path environmentVariablePath = Paths.get(environmentVariable);
            if (Files.exists(environmentVariablePath))
            {
                Path resolvedEnvironmentVariableFilePath = environmentVariablePath.resolve(executableFileName);
                if (Files.isExecutable(resolvedEnvironmentVariableFilePath))
                {
                    return true;
                }
            }
        } catch (InvalidPathException exception)
        {
            exception.printStackTrace();
        }
    }

    return false;
}

总体而言,这现在可能是最有效,最可靠的解决方案。

答案 8 :(得分:0)

你可以在windows下使用where命令。假设您检查 git-bash.exe 应用程序是否在 Windows 路径上。您必须运行 shell 命令:cmd /c where git-bash。然后在返回的修剪后的字符串上,您可以执行以下操作: if(shellResult!=null && shellResult.endsWith('git-bash.exe')) ..... do you things