I'm having some issues with ProcessBuilder.start();
.
Here's an example of what the code looks like:
List<String> listOfStrings = new ArrayList<String>();
myListOfString.add("zip");
myListOfString.add("-r");
myListOfString.add(destinationPath);
myListOfString.add(newFilePath);
File zipFile = new File(workingDirectory, fileName + ".zip");
ProcessBuilder processBuilder = new ProcessBuilder(listOfStrings);
prcoessBuilder.directory(workingDirectory);
try{
Process p = processBuilder.start();
...
...
...
workingDirectory
has been verified to be a working directory using workingDirectory.isDirectory()
.
The issue occurs at Process p = processBuilder.start();
where it throws an IOException.
Below is the stacktrace:
java.io.IOException: Cannot run program "zip" (in directory "<Path to workingDirectory>"): error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
...
...
...
workingDirectory
does not point to a specific file (E.g.: /path/to/
, not /path/to/file.zip
), however, it is a valid directory. Is that possibly the issue?
I cannot give the exact code due to the nature of the project, but I can't imagine the input matters too much if it's crashing at Process p = processBuilder.start();
, however, this is why I'm reaching out so it might be the case.
Let me know if any clarification is needed.
The error message says that Java does not find an executable called zip
in the current directory or on the path, which can be seen with:
String systemPath = System.getenv("PATH");
System.out.println("PATH="+systemPath);
Fix your launcher to include the full path to "zip" or fix the PATH used for your Java VM to include a directory that contains zip
.
myListOfString.add("/the/path/to/zip");
or something like this (depending on your shell / terminal)
export PATH=/the/path/to:$PATH
As @Abra suggests, there are better ways to ZIP inside Java without relying on ProcessBuilder such as:
public static void zip(Path dir, Path zip) throws IOException
{
Map<String, String> env = Map.of("create", "true");
try (FileSystem fs = FileSystems.newFileSystem(zip, env))
{
// This predicate processed the action because it makes use of BasicFileAttributes
// Rather than process a forEach stream which has to call Files.isDirectory(path)
BiPredicate<Path, BasicFileAttributes> foreach = (p,a) -> {
copy(p,a, fs.getPath("/"+dir.relativize(p)));
return false;
};
Files.find(dir, Integer.MAX_VALUE, foreach).count();
}
System.out.println("ZIPPED "+dir +" to "+zip);
}
private static void copy(Path from, BasicFileAttributes a, Path target)
{
System.out.println("Copy "+(a.isDirectory() ? "DIR " : "FILE")+" => "+target);
try
{
if (a.isDirectory())
Files.createDirectories(target);
else if (a.isRegularFile())
Files.copy(from, target, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e)
{
throw new UncheckedIOException(e);
}
}