当尝试复制在Linux子系统(WSL)Ubuntu 16.04的Windows子系统中运行的.jar
脚本中创建的文件时,出现以下错误:
错误执行:cp:无法统计'“ / mnt / e / 18-09-19':没有此类文件或目录
执行不正确:cp:无法统计“文档”:没有此类文件或目录
错误执行:cp:无法统计“某物/某物/某物/ PublicCodeLibrary / Java / mweCopy0 / vars”:没有此类文件或目录
或者,如果执行的命令在源路径中不带引号:
错误执行:cp:无法打开“ / mnt / e / 18-09-19”以供阅读:权限被拒绝
执行不正确:cp:无法统计“文档”:没有此类文件或目录
错误执行:cp:无法统计“某物/某物/某事/ PublicCodeLibrary / Java / mweCopy0 / vars”:没有此类文件或目录
但是,为了验证它是否有效,我还将命令打印到终端,并且在复制粘贴/手动执行该命令时,它确实有效,因为它更改了/usr/share/taskd/pki/vars
文件的内容。
因此,我建立了一个最小的工作示例(MWE),并使用以下命令运行脚本/ MWE:java -jar mweCopy0.jar
。
package mweCopy0;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.ArrayList;
public class mweCopy0 {
public static void main(String[] args) {
String vars = "vars";
char quotation = (char)34; // quotation mark "
String serverName = "exampleName";
//get the path of this file
String linuxPath = getJarLocation()[0];
// create the vars file
createVars(vars,serverName);
// execute commands
generateCommand(false,linuxPath,vars);
}
/**
* Generates the copying command and executes it.
* @param testRun
* @param linuxPath
* @param vars
*/
private static void generateCommand(boolean testRun,String linuxPath,String vars) {
//get commands
String[] commands = new String[24];
char quotation = (char)34; // quotation mark "
//commands[8] = "cp "+quotation+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki/"+quotation+quotation;
//commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki/"+quotation;
//commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki"+quotation;
//commands[8] = quotation+"cp "+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki"+quotation+quotation;
//commands[8] = "cp "+quotation+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki"+quotation+quotation;
//commands[8] = "cp "+quotation+quotation+linuxPath+vars+" "+"/usr/share/taskd/pki"+quotation+quotation;
//commands[8] = "cp "+quotation+quotation+linuxPath+vars+" "+"~"+quotation+quotation;
//commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+"~";
//commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+quotation+"/usr/share/taskd/pki/vars"+quotation;
//commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+"/usr/share/taskd/pki/vars";
commands[8] = "cp "+quotation+linuxPath+vars+quotation+" "+"/usr/share/taskd/pki/";
runCommands(commands[8], false);
System.out.println("Ran:"+commands[8]);
}
/**
* This creates the Vars file required in command 8
* @param serverName
*/
private static void createVars(String fileName, String serverName) {
char quotation = (char)34; // quotation mark "
deleteFile(fileName);
PrintWriter writer;
try {
writer = new PrintWriter("vars", "UTF-8");
writer.println("BITS=4096");
writer.println("EXPIRATION_DAYS=365");
writer.println("ORGANIZATION="+quotation+"Göteborg Bit Factory"+quotation);
writer.println(serverName);
writer.println("COUNTRY=SE");
writer.println("STATE="+quotation+"Västra Götaland"+quotation);
writer.println("LOCALITY="+quotation+"Göteborg"+quotation);
writer.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Delete a file that is located in the same folder as the src folder of this project
* is located.
* @param fileName
*/
private static void deleteFile(String fileName) {
File file = new File(fileName);
try {
boolean result = Files.deleteIfExists(file.toPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //surround it in try catch block
}
/**
* This runs the command for the scenario where you are not prompted for yes.
* Source: https://github.com/AlvinFDK/FDK/blob/18d61bcc2121b13ae1b02345930f6f2264feb813/src/main/java/blackflames/alvin/bar/io/TerminalUnix.java
*/
public static ArrayList<ArrayList<String>> runCommands(String command,boolean ignoreOutput) {
String s = null;
String outputLines=null;
ArrayList<String> goodExecutionOutput=new ArrayList<String>();
ArrayList<String> errorExecutionOutput=new ArrayList<String>();
ArrayList<ArrayList<String>> returnLists = new ArrayList<ArrayList<String>>();
try {
// run the Unix "task nice0" command
Process p = Runtime.getRuntime().exec(command);
BufferedReader brGood = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// get output
if (!ignoreOutput) {
while ((s = brGood.readLine()) != null) {
//System.out.println("Adding:"+s);
goodExecutionOutput.add(s);
System.out.println("Good execution: "+s);
}
// get the error message
while ((s = brError.readLine()) != null) {
errorExecutionOutput.add(s);
System.out.println("Bad execution: "+s);
}
}
//System.exit(0);
}
catch (IOException e) {
System.out.println("Error: ");
e.printStackTrace();
System.exit(-1);
}
//Merge outputLists and return
returnLists.add(goodExecutionOutput);
returnLists.add(errorExecutionOutput);
return returnLists;
}
/**
* This gets the current location of the compiled.jar file
* @return
*/
public static String[] getJarLocation() {
String[] paths= new String[2];
// get path of location of compiled .jar file of this project in windows format
File f = new File(System.getProperty("java.class.path"));
File dir = f.getAbsoluteFile().getParentFile();
paths[0] = dir.toString()+"/";
return paths;
}
}
问题:
如何从.jar
文件中复制WSL Ubuntu 16.04中的文件?
其他尝试:
我知道,当用户键入内容时,以及从这样的.jar
文件执行命令时,终端如何处理命令。具体来说,某些语法无法正常工作,因为您需要将命令的输出通过管道传输到输入,反之亦然,cd
命令的功能也有所不同。但是,我尚无法确定cp
命令为何会受到这两种现象的影响,因为没有与此命令相关的输出,并且唯一的相对环境是Unix环境。>
根据评论进行更新:*
实际上,显式引号使路径无效。此外,在结束路径中,不应包含输出文件,因此将vars
末尾的command[8]=...
删除。但是,由于源路径的前8个字符中可能包含空格,因此我目前正在研究如何在不添加其他显式引号的情况下在命令中包含空格。
答案 0 :(得分:0)
解决方案:
找到了解决方案,方法是将命令和参数分别分隔在一个单独的字符串中,然后按照注释中的建议将分隔的字符串数组传递给Runtime.getRuntime()。exec(command)。
注释:
实施:
使用两个额外的类找到一个实现。对于此应用程序,我只是在项目src
文件夹(与主类位于同一文件夹)中添加了两个类。额外的类runCommandsWithArgs.java
和SyncPipe.java
列在主类下方(名为mweCopy0.java
)。
mweCopy0.java
:
package mweCopy0;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.ArrayList;
public class Main {
/**
* First the main gets the location for the file that it wants to copy somewhere.
* Next it creates the file it wants to copy somewhere.
* Then it generates the command to copy the file somewhere.
* In method generateCommand, the command is passed through
* to the module that actually executes the command in WSL Ubuntu 16.04.
*
* You can quickly compile this script in Eclipse by:
* Selecting Main.java in the Package Explorer,
* press: alt+f>o>
* Then select Java>Runnable JAR file>next
* In launch configuration, select the Main.java
* Select Package required libraries into generated JAR
* press finish.
* @param args
*/
public static void main(String[] args) {
String vars = "vars";
char quotation = (char)34; // quotation mark "
String serverName = "exampleName";
//get the path of this file
String linuxPath = getJarLocation()[0];
// create the vars file
createVars(vars,serverName);
// execute commands
generateCommand(false,linuxPath,vars);
}
/**
* Generates the copying command and calls the class that executes it.
* @param testRun
* @param linuxPath
* @param vars
*/
private static void generateCommand(boolean testRun,String linuxPath,String vars) {
String[] commands = new String[24];
char quotation = (char)34; // quotation mark "
// attempt 1: Original command
// cp /mnt/e/18-09-19 Document structure/personal/Programming/PublicCodeLibrary/Java/mweCopy0/vars /usr/share/taskd/pki/
// separate the command from its arguments with a space between the arguments:
// note it is irrelevant whether the arguments themselves contain spaces.
String[] commandAndArgs = new String[3];
commandAndArgs[0] = "cp";
commandAndArgs[1] = "/mnt/e/18-09-19 Document structure/personal/Programming/PublicCodeLibrary/Java/mweCopy0/vars";
commandAndArgs[2] = "/usr/share/taskd/pki/";
RunCommandsWithArgs.runCommands(commandAndArgs);
System.out.println("Ran:"+commandAndArgs);
}
/**
* This creates the Vars file required in command 8
* @param serverName
*/
private static void createVars(String fileName, String serverName) {
char quotation = (char)34; // quotation mark "
deleteFile(fileName);
PrintWriter writer;
try {
writer = new PrintWriter("vars", "UTF-8");
writer.println("BITS=4096");
writer.println("EXPIRATION_DAYS=365");
writer.println("ORGANIZATION="+quotation+"Göteborg Bit Factory"+quotation);
writer.println(serverName);
writer.println("COUNTRY=SE");
writer.println("STATE="+quotation+"Västra Götaland"+quotation);
writer.println("LOCALITY="+quotation+"Göteborg Verification"+quotation);
writer.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Delete a file that is located in the same folder as the src folder of this project
* is located.
* @param fileName
*/
private static void deleteFile(String fileName) {
File file = new File(fileName);
try {
boolean result = Files.deleteIfExists(file.toPath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //surround it in try catch block
}
/**
* This gets the current location of the compiled.jar file
* @return
*/
public static String[] getJarLocation() {
String[] paths= new String[2];
// get path of location of compiled .jar file of this project in windows format
File f = new File(System.getProperty("java.class.path"));
File dir = f.getAbsoluteFile().getParentFile();
paths[0] = dir.toString()+"/";
return paths;
}
}
RunCommandsWithArgs.java
:
package mweCopy0;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
public class RunCommandsWithArgs {
/**
* This method actually executes the command in WSL Ubuntu 16.04 if you run the
* compiled .JAR file.
* You can automatically answers yes to any input the command requires with the
* stdin.println("yes"); line
* @param command
* @return
*/
public static void runCommands(String[] commandPart) {
Process p;
try {
p = Runtime.getRuntime().exec(commandPart);
new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
PrintWriter stdin = new PrintWriter(p.getOutputStream());
//This is not necessary but can be used to answer yes to being prompted
//stdin.println("yes");
// write any other commands you want here
stdin.close();
int returnCode = p.waitFor();
System.out.println("Return code = " + returnCode);
} catch (IOException | InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
SyncPipe.java
:
package mweCopy0;
import java.io.InputStream;
import java.io.OutputStream;
class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
istrm_ = istrm;
ostrm_ = ostrm;
}
public void run() {
try
{
final byte[] buffer = new byte[1024];
for (int length = 0; (length = istrm_.read(buffer)) != -1; )
{
ostrm_.write(buffer, 0, length);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private final OutputStream ostrm_;
private final InputStream istrm_;
}