How to access file path with spaces from command prompt in Java

3.1k views Asked by At

I am trying to run a batch file from a Java program. For instance: I have a batch "abc.bat" in a folder in "Program Files".

I want to execute this batch from my Java Program. I am using CommandLine class, Commons-exec jar.

CommandLine cmdLine = CommandLine.parse("cmd");
cmdLine.addArgument("/c start \"\" \"C:\\Program Files\\abc.bat\"");

DefaultExecutor exec = new DefaultExecutor();
Process p = Runtime.getRuntime().exec(cmdLine.toString());
exec.execute(cmdLine);

The above code throws an error saying "Windows cant find the file. Make sure you typed the name correctly, and try again". And, that is because of the spaces in the path.

So, I tried the answer provided here by @brso05 and that works. But I want it to be in a Future Class. Please find my code below and help me fix it.

final CommandLine cmdLine = CommandLine.parse("cmd.exe");
cmdLine.addArgument("/c");
cmdLine.addArgument("start");
cmdLine.addArgument("\""+ batchFileExecute.getParent().toString() + "\"");

ExecutorService es = Executors.newFixedThreadPool(1);
Future<?> future = es.submit(new Runnable() {
        public void run() {
                DefaultExecutor exec = new DefaultExecutor();
                        try {
                            Process p = Runtime.getRuntime().exec(cmdLine.toString());
                            exec.execute(cmdLine);
                            System.out.println(p.waitFor());
                            }
                        catch (IOException e) 
                            {
                                e.printStackTrace();
                            }
                        catch (InterruptedException e)
                            {
                                e.printStackTrace();
                            }
                        }
                        });
                            String thread_status = null;
                            try 
                            {
                                thread_status = future.get().toString(); 
                                System.out.println(thread_status+" completed the execution");
                            } 
                            catch (NullPointerException e) 
                            {
                            System.out.println("The execution of the received project is     complete.");                   
// In here I want to do some processing again.
}

The code I mentioned works but it doesnt work if my batch file has a spaces in the path. Can you help me fix this?

Becuase the snippet you've given works but then I cant put it into Future. It doesnt work in the desired manner.

Thanks in advance!

4

There are 4 answers

0
Murat Aykanat On

I had the same filenames with spaces issue while using ImageMagick. Here is the code to solve the issue:

String imageOutput = null;
ByteArrayOutputStream identifyStdout = new ByteArrayOutputStream();
ByteArrayOutputStream identifyStderr = new ByteArrayOutputStream();

try
{
    DefaultExecutor identifyExecutor = new DefaultExecutor();
    // End the process if it exceeds 60 seconds
    ExecuteWatchdog identifyWatchdog = new ExecuteWatchdog(60000);
    identifyExecutor.setWatchdog(identifyWatchdog);


    PumpStreamHandler identifyPsh = new PumpStreamHandler(identifyStdout, identifyStderr);
    identifyExecutor.setStreamHandler(identifyPsh);
    identifyExecutor.setExitValue(0); //0 is success

    CommandLine identifyCommandline = new CommandLine("identify");
    identifyCommandline.addArgument(destFile.getAbsolutePath(), false);

    DefaultExecuteResultHandler identifyResultHandler = new DefaultExecuteResultHandler();

    identifyExecutor.execute(identifyCommandline, identifyResultHandler);
    identifyResultHandler.waitFor();

    if (identifyResultHandler.getExitValue() != 0)
    {
        String output = identifyStdout.toString();
        _logger.debug("Standard Out = " + output);
        _logger.debug("Standard Err = " + identifyStderr.toString());

        String msg = "ImageMagick overlay encountered an error. ImageMagick returned a value of " + identifyResultHandler.getExitValue();
        throw new Exception(msg);
    }
    else
    {
        imageOutput = identifyStdout.toString();
        _logger.debug("Standard Out = " + imageOutput);
        identifyStdout.close();
        identifyStderr.close();
    }
}
catch(Exception e)
{
    _logger.debug("Error: " + e.getLocalizedMessage(), e);
}
finally
{
    identifyStdout.close();
    identifyStderr.close();
}

The important part here is:

identifyCommandline.addArgument(destFile.getAbsolutePath(), false);

This line allows a filepath with spaces to process correctly.

1
jmm On

Have you tried with single quotes? According to this, it should work.

2
brso05 On

This is an alternative way:

     Runtime rt = Runtime.getRuntime();
     rt.exec("cmd.exe /c start \"\" \"C:\\Program Files\\abc.bat\"");
0
frankmurphy On

When using the CommandLine class addArgument method without defining the boolean handleQuoting, it will set handleQuoting to true for you, basically adding quotes to the argument. This is the method invoking:

    public CommandLine addArgument(String argument) {
        return this.addArgument(argument, true);
    }

    public CommandLine addArgument(String argument, boolean handleQuoting) {
        if (argument == null) {
            return this;
        } else {
            if (handleQuoting) {
                StringUtils.quoteArgument(argument);
            }

            this.arguments.add(new Argument(argument, handleQuoting));
            return this;
        }
    }

Changing my method from:

        CommandLine cmd = new CommandLine("pdfinfo");
        cmd.addArgument("-box");
        cmd.addArgument(pdfFile.getAbsolutePath());

To:

        CommandLine cmd = new CommandLine("pdfinfo");
        cmd.addArgument("-box");
        cmd.addArgument(pdfFile.getAbsolutePath(), false); <-- change here

Solved the issue for me. No quotes were added and the CommandLine was able to find the file.