【问题标题】:Copy file using `.jar` in WSL Ubuntu 16.04在 WSL Ubuntu 16.04 中使用 .jar 复制文件
【发布时间】:2019-08-23 19:39:17
【问题描述】:

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

错误执行:cp: cannot stat '"/mnt/e/18-09-19': No such file or directory

执行错误:cp: cannot stat 'Document': No such file or directory

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

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

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

执行错误:cp: cannot stat 'Document': No such file or directory

错误执行:cp: cannot stat 'something/something/Something/PublicCodeLibrary/Java/mweCopy0/vars': No such file or directory

但是,为了验证它是否有效,我还将命令打印到终端,当我复制粘贴/手动执行它时,它确实有效,因为它更改了 /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;
    }
}

问题:

如何在 WSL Ubuntu 16.04 中从 .jar 文件中复制文件?

其他尝试:

我知道,当用户键入时,终端处理命令的方式与从 .jar 这样的文件执行命令时,终端处理命令的方式有所不同。具体来说,某些语法不起作用,因为您需要将命令的输出通过管道传输到输入,反之亦然,cd 命令的功能也不同。但是,我还不能确定为什么cp 命令会受到这两种现象的影响,因为没有与此命令功能相关的输出,唯一的相对环境是 Unix 环境。

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

【问题讨论】:

  • 请注意,它在抱怨"/usr/share/taskd/pki/" 带双引号 - 我确定不存在。尝试在命令行上以'"/usr/share/taskd/pki/"' 运行它,你会遇到同样的问题。不要创建命令行,而是使用接受数组的Runtime.exec 版本。或使用ProcessBuilder
  • 非常感谢您的回复,这确实是由于引号导致的无效路径,而且输出文件vars不应包含在目标路径中。然而,我仍然面临的困难包括(潜在的)空格(带有)在我的源路径(前 8 个字符)中,而不添加/包括引号。我正在寻找解决方案。如果这不起作用,我将研究 ProcessBuilder 并将我的尝试包含在 Runtime.getRuntime().exec(command) 方法中。
  • 在带有数组的版本中,您在第一个元素中传递命令名称,在下一个元素中传递第一个参数等。每个参数可能包含空格或特殊字符或其他任何内容。因为它不通过外壳,所以没关系。

标签: java copy ubuntu-16.04 executable-jar windows-subsystem-for-linux


【解决方案1】:

解决方案:

找到了一个解决方案,方法是将命令和参数分别放在一个单独的字符串中,然后按照 cmets 中的建议将分隔字符串数组传递给 Runtime.getRuntime().exec(command)。

注意事项:

  1. 参数是否包含空格,是ir相关的。
  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_;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    相关资源
    最近更新 更多