2017-03-04 121 views
6

原帖的大多数人都回答如何检索在Java中运行进程的工作目录?

下面一个是我已经尝试与

String workingDirectory = "/home"; 
String command = "cd ../"; 

ProcessBuilder pb = new ProcessBuilder(new String[] { "cmd", "/c", command }); 
pb.directory(new File(workingDirectory)); 
pb.redirectErrorStream(true); 
Process process = pb.start(); 

// Some time later once the process has been closed 
workingDirectory = pb.directory().getAbsolutePath(); 
System.out.println("Path: " + workingDirectory); 

这样做这是不行的,一旦它完成它出来与代码同样的 工作目录。

任何帮助将不胜感激,这将是一个非常有用的 认为知道。

更具体地说,我期待在Java中找到 动态创建的进程的工作目录,例如上面的代码片段。 这很重要,因为如上面预定义的命令, 工作目录有时可能会更改,我想将任何 更改保存到内存中供以后使用。

我找到了一种方法来做到这一点,似乎工作没有问题

这里是我正在处理输入的工作目录

public int osType = 1; // This is for Windows (0 is for Linux) 

public boolean isValidPath(String path) { 
    try { 
     Paths.get(new File(path).getAbsolutePath()); 
    } catch (InvalidPathException | NullPointerException ex) { 
     return false; 
    } 
    return true; 
} 

public String tracePath(String path) { 
    try { 
     if (!path.contains("%%") && !isValidPath(path)) return null; 
     if (path.contains("%%")) path = path.substring(path.indexOf("%%")); 
     int lastIndex = -1; 
     char filesystemSlash = ' '; 
     if (osType == 0) 
      filesystemSlash = '/'; 
     if (osType == 1) 
      filesystemSlash = '\\'; 
     if (osType == 0) 
      path = path.substring(path.indexOf(filesystemSlash)); 
     if (osType == 1) 
      path = path.substring(path.indexOf(filesystemSlash) - 2); 
     String tmp = path; 
     boolean broken = true; 
     while (!isValidPath(tmp)) { 
      int index = tmp.lastIndexOf(filesystemSlash); 
      if (lastIndex == index) { 
       broken = false; 
       break; 
      } 
      tmp = tmp.substring(0, index); 
      lastIndex = index; 
     } 
     if (broken && lastIndex != -1) { 
      tmp = path.substring(0, lastIndex); 
     } 
     return tmp; 
    } catch (StringIndexOutOfBoundsException ex) { 
     return null; 
    } 
} 

这里是忽略的方法与路径问题(不使用它)

public boolean setDirectory(ProcessBuilder pb, String path) { 
    try { 
     pb.directory(new File(new File(path).getAbsolutePath())); 
     return true; 
    } catch (Exception ex) { 
     return false; 
    } 
} 

现在这里是怎么了开始为Windows或Linux的过程

File file = null; 
     if (osType == 1) { 
      ProcessBuilder pb = new ProcessBuilder(new String[] { "cmd", "/c", command + " & echo %% & cd" }); 
      pb.redirectErrorStream(true); 
      if (!workingDirectory.equals("")) 
       setDirectory(pb, workingDirectory); 
      process = pb.start(); 
     } else if (osType == 0) { 
      file = new File("script.sh"); 
      FileWriter writer = new FileWriter(file, false); 
      writer.append(command + " && echo %% && pwd"); 
      writer.flush(); 
      writer.close(); 
      ProcessBuilder pb = new ProcessBuilder(new String[] { "bash", System.getProperty("user.dir") + "/script.sh" }); 
      pb.redirectErrorStream(true); 
      if (!workingDirectory.equals("")) 
       setDirectory(pb, workingDirectory); 
      process = pb.start(); 
     } else 
      return; 

最后这里是管理过程中的循环和工作目录

while (process.isAlive() || process.getInputStream().available() > 0) { 
      byte[] returnBytes = new byte[1024]; 
      process.getInputStream().read(returnBytes); 
      char[] arr = new String(returnBytes).trim().toCharArray(); 
      StringBuilder sb = new StringBuilder(); 
      for (int i = 0; i < arr.length; i++) { 
       char c = arr[i]; 
       if (Character.isDefined(c)) 
        sb.append(c); 
      } 
      String response = sb.toString(); 
      if (!response.equals("")) { 
       String path = tracePath(response.trim().replace("\n", "").replace("\r", "")); 
       if (path != null && osType == 1) { 
        if (Paths.get(path).toFile().exists()) 
         workingDirectory = path; 
       } else if (path != null && osType == 0) { 
        if (Paths.get(path).toFile().exists()) 
         workingDirectory = path; 
       } 
       client.sendMessage(response + '\r' + '\n'); 
      } 
     } 
if (file != null) file.delete(); 

下面是从命令接收输出的网站

Connecting.. 
Connected. 
Success. You have been connected -> Speentie 

bash -c pwd 
/root/hardsceneServer/remoteServer 

%% 
/root/hardsceneServer/remoteServer 

bash -c cd .. 

%% 
/root/hardsceneServer 

bash -c pwd 
/root/hardsceneServer 

%% 
/root/hardsceneServer 

bash -c dir 
ircServer nohup.out remoteServer start.sh start1.sh start2.sh 

%% 
/root/hardsceneServer 

bash -c cd ircServer 

%% 
/root/hardsceneServer/ircServer 

bash -c dir 
HardScene.jar   hardscene_banned.properties start.sh 
hardscene.properties nohup.out 

%% 
/root/hardsceneServer/ircServer 
+0

什么是命令吗? –

+0

如果你问如何检索另一个进程的工作目录,那么这是不可能的。 – Andreas

+0

当Linux可以做到这一点时,它是不可能的?我以为Java也可以与机器接口?必须有一种方法,即使它非常复杂。 – Speentie8081

回答

4

你在找这样的东西吗?

System.out.println("Current working directory: " + System.getProperty("user.dir")); 
System.out.println("Changing working directory..."); 
// changing the current working directory 
System.setProperty("user.dir", System.getProperty("user.dir") + "/test/"); 

// print the new working directory path 
System.out.println("Current working directory: " + System.getProperty("user.dir")); 

// create a new file in the current working directory 
File file = new File(System.getProperty("user.dir"), "test.txt"); 

if (file.createNewFile()) { 
    System.out.println("File is created at " + file.getCanonicalPath()); 
} else { 
    System.out.println("File already exists."); 
} 

它输出:

Current working directory: /Users/Wasi/NetBeansProjects/TestProject 
Changing working directory... 
Current working directory: /Users/Wasi/NetBeansProjects/TestProject/test/ 
File is created at /Users/Wasi/NetBeansProjects/TestProject/test/test.txt 
+0

不是真的,你几乎可以得到它,当人们在命令窗口中执行某些“cd ../”命令时,会看到它为那一个命令执行了操作,但它不会将该新目录保存在Java中的内存中存储在一个全新的过程中。所以我需要的只是通过某种方式来传递进程并获取该进程的工作目录,以便稍后可以重用它。 – Speentie8081

+0

@SkorrloreGaming我找到了你。但为什么不使用'System.getProperty(“user.dir”)'?你想只保存一个进程的当前工作目录吗? –

+0

我想具体的动态过程的工作目录没有其他 – Speentie8081

2

我希望找到在Java中动态创建的进程的工作目录,

你当然可以查找的工作目录当前Java进程通过查看user.dir系统属性的值:

String cwd = System.getProperty("user.dir"); 

但找到的工作目录另一个进程是不可能的,除非您使用特殊的OS调用。在Linux上,如果你知道pid,那么你可以看看/proc/[pid]/cwd,但在我知道的OSX或Windows中没有简单的等价物。

这不起作用,一旦它完成它出来了相同的工作目录。

是的,你不能发出命令来改变工作目录,因为一旦cmd退出,工作目录将被重置。

this page,您可以通过分配user.dir系统属性设置工作目录:

System.setProperty("user.dir", "/tmp"); 

然而,这可能是OS依赖和对我的OSX箱不起作用。例如,下面的代码创建在同一个目录中x1x2文件:

new File("x1").createNewFile(); 
// this doesn't seem to do anything 
System.setProperty("user.dir", "/tmp"); 
new File("x2").createNewFile(); 

This answer说有在Java中做到这一点没有可靠的方法。我一直认为你不能改变工作目录,并且你应该使用new File(parent, filename)来显示文件的存在位置等。

0

你可以做的是使用sysinternals for windows的句柄

https://technet.microsoft.com/en-us/sysinternals/bb896655.aspx

LS -l/PROC/[PID]/FD或PFILES [PID]为Linux

,发现最后由该方法中使用的文件夹。

String commandToGetOpenFiles="handle... or ls..."; 
BufferedReader reader = new BufferedReader(
     new InputStreamReader(Runtime.getRuntime() 
       .exec(commandToGetOpenFiles).getInputStream())); 

,并开始您处理,并得到PID使用WMIC过程调用创建“CMD”

0

使用此为您在目前的文件目录的URL:

URL url = ClassLoader.getSystemResource(FileName); 

它工作在任何地方。不只是你的电脑,即使在云端。

它返回一个URLjava.net)类型。对于ClassLoader,您不需要导入任何内容。

文件名中,使用您想要获取路径的任何文件名。

-1

使用下面的代码

Path currentRelativePath = Paths.get(""); 
String s = currentRelativePath.toAbsolutePath().toString(); 
System.out.println("Current relative path is: " + s); 
2

它不能在Java中由ProcessBuilderdirectory()方法,因为它设置了一个进程的工作目录,而不是其中的二进制是实现的。你必须在另一个层面做到这一点。

如果您使用的是GNU/Linux,whereisupdate-alternative是您最好的选择。在Windows中,您有where。现在,它涉及到在不同操作系统中使用命令以及解析输出。这可能很难。

一些伪代码开始:

  1. 执行whereis加上命令参数,与ProcessBuilder
  2. 尝试解析输出。你可能会处理多行输出。

或者,

  1. 执行update-alternatives加上命令参数,与ProcessBuilder
  2. 尝试解析输出。一个命令可能有多种选择,例如java,您可能安装了一些不同的JDK。
  3. 或者,列出/var/libs/alternatives中的所有链接,并找到你想要的东西,也许用管道。你可以在这里看到:

https://serverfault.com/questions/484896/is-there-a-way-to-list-all-configurable-alternatives-symlinks-for-similar-com

但是,我还是怀疑你为什么这样做。所以,如果你能澄清原来的要求,这将有很大的帮助。这是为了避免X-Y problem

+0

+1这对于Linux用户很有用,但是在测试中这不会按预期工作。我正在寻找该项目的Windows和Linux解决方案,但这不是一个。不过谢天谢地,我在发布的时候自己找到了一个解决方案。 – Speentie8081

+0

那么,毕竟你的解决方案是什么?它令我感兴趣。 – FaithReaper

+0

我发布了我用作编辑问题的最新代码。 – Speentie8081

0

你的问题不清楚了一点,但如果你想从内部当前进程查找当前目录,只是做

new File("").getAbsoluteFile().getAbsolutePath(); 
相关问题