Reputation:
Original post the one that most people were answering
Here is the code I have already tried doing this with
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);
This does not work, once it finishes it comes out with the same working directory.
Any help would be greatly appreciated, this would be a very useful think to know.
To be more specific, I am looking to find the working directory of a dynamically created process in Java, such as in the snippet above. This is important because such as the predefined command above, working directories can change sometimes, I would like to save any changes into memory for later use.
I found a way to do this, and it seems to work problem free
Here is how I am handling the incoming working directory
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;
}
}
Here is the method of ignoring issues with the path (by not using it)
public boolean setDirectory(ProcessBuilder pb, String path) {
try {
pb.directory(new File(new File(path).getAbsolutePath()));
return true;
} catch (Exception ex) {
return false;
}
}
Now here is how I am starting the process for Windows or 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;
Finally here is the loop that manages the process and the working directory
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();
Here is the output from the command receiving website
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
Upvotes: 6
Views: 4103
Reputation: 1
Your question is unclear a bit, but if you're trying to find the current directory from WITHIN the current process, just do
new File("").getAbsoluteFile().getAbsolutePath();
Upvotes: 0
Reputation: 12787
It cannot be achieved in Java by ProcessBuilder
's directory()
method because it sets the working directory of a process, not where the binary is. You have to do it in another level.
If you are working with GNU/Linux, whereis
and update-alternative
are your best bet. In Windows, you have where
. Now, it comes to the usage of commands in different OS, and the parsing of the outputs. It may be hard.
Some pseudo code to begin with:
whereis
plus the command as parameter, with ProcessBuilder
Or,
update-alternatives
plus the command as parameter, with ProcessBuilder
java
, you may have some different JDKs installed./var/libs/alternatives
and find what you want, maybe with pipe. You can see here: But, I still doubt why you are doing this. So, if you can clarify the original requirements, it would help a lot. It's for avoiding X-Y problem.
Upvotes: 1
Reputation: 5
Use this to get the URL of your current file directory:
URL url = ClassLoader.getSystemResource(FileName);
It works anywhere. Not just your PC, even in cloud.
It returns an URL(java.net) type. For ClassLoader, you don't need to import anything.
In the FileName, use any filename you want to get the path for.
Upvotes: 0
Reputation: 648
use the below code
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
System.out.println("Current relative path is: " + s);
Upvotes: -1
Reputation: 11
What you can do is to use handle from sysinternals for windows
https://technet.microsoft.com/en-us/sysinternals/bb896655.aspx
or
ls -l /proc/[PID]/fd or pfiles [PID] for linux
and find a folder that was last used by that process.
String commandToGetOpenFiles="handle... or ls...";
BufferedReader reader = new BufferedReader(
new InputStreamReader(Runtime.getRuntime()
.exec(commandToGetOpenFiles).getInputStream()));
and to start you process and get PID use wmic process call create "cmd"
Upvotes: 0
Reputation: 116908
I am looking to find the working directory of a dynamically created process in Java,
You can certainly lookup the working directory of the current Java process by looking at the value of the user.dir
system property:
String cwd = System.getProperty("user.dir");
But finding out the working directory of another process is not possible unless you are using special OS calls. On Linux, if you know the pid then you can look at /proc/[pid]/cwd
but there is no easy equivalent in OSX or Windows that I know about.
This does not work, once it finishes it comes out with the same working directory.
Yeah, you are not able to issue a command to change the working directory because once the cmd exits, the working directory will be reset.
According to this page, you can set the working directory by assigning the user.dir
system property:
System.setProperty("user.dir", "/tmp");
However this may be OS dependent and doesn't work on my OSX box. For example, the following code creates the x1
and x2
files in the same directory:
new File("x1").createNewFile();
// this doesn't seem to do anything
System.setProperty("user.dir", "/tmp");
new File("x2").createNewFile();
This answer says that there is no reliable way to do this in Java. I've always taken the opinion that you can't change the working directory and that you should be specific with new File(parent, filename)
to show where files live, etc..
Upvotes: 2
Reputation: 37741
Are you looking for something like this?
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.");
}
It outputs:
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
Upvotes: 3