경로

2009-06-01 2 views
13

내가 전화 스칼라에서 프로그램 쓰고 있어요에서 프로그램의 존재를 확인하는 방법 :. "SVN은"명령 줄에서 사용할 수있는 경우경로

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

내가 확인하려면 (즉 그것은 도달 PATH에 있음). 어떻게해야합니까?

는 PS : 내 프로그램은 윈도우에서 실행되도록 설계

답변

13

내가 더 스칼라 프로그래머는 아니지만, 내가 어떤 언어로 어떻게 할 것인지, 단지 (리턴 코드를 확인하기 위해 'svn help'같은 것을 실행하는 것입니다 그것은 SVN 실패하면 0 또는 1)에있어서의 간부 ... 경로에 있지 : P 관례

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

, 값 0은 정상 종료를 나타낸다.

+0

내가 대신 'svn의 도움을 "의"svn을하는 "할 더 좋을 거라 생각 :

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; } 

여기 도우미입니다. svn이 경로에 존재하는지 여부에 대한 적절한 반환 코드를 제공하지만 성공하면 svn 실행 파일에 대한 전체 경로도 가져옵니다. – Apreche

+5

"which"는 Windows 명령이 아닙니다. – EMMERICH

+0

"where는"Windows "의"which "입니다. –

2

원래 질문에 대해서는 FMF가 제시 한대로 존재하는지 확인합니다.

적어도 프로세스의 출력을 처리하고 사용 가능한 데이터를 읽어야 스트림이 가장자리에 채워지지 않도록해야한다는 점을 지적하고자합니다. 이렇게하면 프로세스가 차단됩니다.

이렇게하려면 proc.getInputStream() (System.out) 및 proc.getErrorStream() (System.err)을 사용하여 프로세스의 InputStream을 검색하고 다른 스레드에서 사용 가능한 데이터를 읽습니다.

이 일반적인 함정과 SVN은 잠재적으로 매우 offtopicness에 대한 downvote하지 말아 주시기 바랍니다 출력 꽤 만들 것이기 ​​때문에 난 그냥 당신에게, 당신이 Cygwin에서 설치 한 경우)

0

먼저 "어떤 SVN 부를 수 ", 실행 경로에있는 경우 svn의 절대 경로를 반환하거나"which : no svn in (...) "을 반환합니다. "which"에 대한 호출은 exitValue가 발견되지 않으면 1을 리턴하고, 발견되면 0을 리턴합니다. FMF 세부 사항에서이 오류 코드를 점검 할 수 있습니다.

13

어쩌면 누군가가 자바 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()로 교체 할 수 있습니다 - 그래서 당신은 정확한 실행 경로를 얻을 수 있습니다.

+0

'Pattern.splitAsStream'을 사용하면 더 좋을 것입니다 ... –

+0

이것을 시도하고 IDE (Eclipse를 사용하고 있습니다)에서 실행하면 내 환경 PATH에 경로가 추가 된 파일을 찾을 수 없습니다 변하기 쉬운. 그러나 실행 가능한 JRE를 만들어 터미널에서 실행하면 작동합니다. 따라서 터미널을 열 때 내 IDE 내에서 내 PATH가 내 PATH와 같지 않은 것 같습니다. 이 문제를 어떻게 해결할 수 있습니까? 코드를 테스트 할 때마다 runnable Jar를 만들지는 않을 것입니다. 감사! – skrilmps

+0

Windows에서도 작동하지 않습니다. 'exec = java'를 설정하면 거짓 결과를 얻습니다. 하지만 cmd에서 'java'를 실행하면 히트가 발생합니다. – skrilmps

4

셀레늄은 셀레늄 3.1 이후 public 액세스 클래스 org.openqa.selenium.os.ExecutableFinder에서 윈도우/리눅스/Mac 용 합리적으로 완벽하게 구현 될 모습이 (비추천 방법 org.openqa.selenium.os.CommandLine#find를 통해 이전에는 접근). ASL 2.0입니다.

ExecutableFinder은 Windows에서 PATHEXT을 인식하지 못합니다. 하드 코딩 된 실행 파일 확장자 (.exe, .com, .bat) 세트 만 있습니다.

+1

이제 공개됩니다. https://github.com/SeleniumHQ/selenium/blob/master/java/client/src/org/openqa/selenium/os/ExecutableFinder.java#L48 – gouessej

+0

감사합니다. @gouessej. 아직 출시되지 않은 것 같습니다 : https://github.com/SeleniumHQ/selenium/blob/selenium-3.0.1/java/client/src/org/openqa/selenium/os/ExecutableFinder.java#L35 – seanf

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 on :

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

는/usr/빈/psql의

이 방법의 장점은 모든 플랫폼에서 작동해야하고 PATH 환경 변수를 구문 분석하거나 레지스트리보고 할 필요가 없습니다 것입니다. 원하는 프로그램이 발견 되더라도 절대로 호출되지 않습니다. 마지막으로 프로그램 확장을 알 필요가 없습니다. Windows의 gnuplot.exe와 Linux의 gnuplot은 모두 같은 코드에서 찾을 수 있습니다.

SimulationUtils.lookForProgramInPath("gnuplot") 

개선을위한 제안은 환영합니다! 내 경험에

+0

이것은 실제로 끔찍한 성능을 가지고 있습니다. 외부 프로세스 호출은 가능한 한 피해야합니다. – BullyWiiPlaza

+1

@BullyWiiPlaza : 좋은 성능을 달성하는 것이 내 목표도 아니 었습니다. Windows/Linux/MacOS에서 작업하면서 더 빠를 수있는 방법이 있다면 언제든지 제안 해주십시오. BTW, 결과를 캐시 할 수 있습니다. 마지막으로 목표는 외부 프로세스를 호출하는 것입니다. 'svn' 호출은'where' 나'which' 호출보다 훨씬 느립니다. –

+0

예, '드미트리 긴츠 부르그 (Gmitzburg Dmitry Ginzburg)'의 대답은 정말 좋습니다. 'where'는 상대적으로 큰 오버 헤드 (100-200ms 이상이 될 수 있습니다.)를 여러 번 호출하면 손에서 빠져 나갑니다. 난 그냥 내 눈에 띄게 느린 이유에 관해서는 이걸 깨달았다. – BullyWiiPlaza

0

종료 아닌지 단지 ProcessBuilder으로 명령을 호출을 통해 다양한 시스템을 통해 말씀 (도 Exceptions을하거나 값이 일치하는 것 같다 반환) 그래서 여기

을 Java7 솔루션은 불가능하다 PATH 환경 변수를 탐색하고 일치하는 도구를 찾습니다. 디렉토리가 있으면 모든 파일을 검사합니다. matchesExecutable은 확장명과 대소 문자를 무시한 도구의 이름이어야합니다.

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; 
}