在 WSL Ubuntu 16.04 中使用".jar"复制文件



尝试复制我在 Windows 子系统 for Linux (WSL) Ubuntu 16.04 中运行的.jar脚本中创建的文件时,收到以下错误:

执行错误:cp:无法统计"/mnt/e/18-09-19":没有这样的文件或目录

执行错误: cp: 无法统计 "文档": 没有这样的文件或目录

执行错误:cp:无法统计"something/something/SomeThing/PublicCodeLibrary/Java/mweCopy0/vars"':没有这样的文件或目录

或者,如果命令在源路径中不带引号执行:

执行错误:cp:无法打开"/mnt/e/18-09-19"进行读取:权限被拒绝

执行错误: cp: 无法统计 "文档": 没有这样的文件或目录

执行错误:cp:无法统计"something/something/Something/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 环境。

根据注释进行更新:*实际上,显式引号使路径无效。此外,在结束路径中,不应包含输出文件,因此删除command[8]=...末尾的vars。但是,由于源路径可能包含前 8 个字符内的空格,因此我目前正在研究如何在命令中包含空格而无需添加额外的显式引号。

解决方案:

通过将命令和参数分别分隔在一个单独的字符串中,并将分隔字符串的数组传递到 Runtime.getRuntime().exec(command) 中,找到了解决方案,如注释中所建议的那样。

笔记:

  1. 参数是否包含任何空格是无关紧要的。
  2. 无论参数是否包含任何空格,参数都不应用引号引起来。

实现:

找到使用两个额外类的实现。对于此应用程序,我刚刚在项目src文件夹中添加了两个类(与主类所在的文件夹相同)。额外的类runCommandsWithArgs.javaSyncPipe.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_;
}

最新更新