Difference between windows and linux with double quotes

263 views
Skip to first unread message

Carl Saint

unread,
Nov 23, 2020, 11:03:15 AM11/23/20
to picocli
Hi,

I am hitting an issue or difference in behaviour when running picocli on windows and linux.

If the command line has something like -

 --json='{"name": "value"}'

parsed on windows - {name: value}
parsed on linux - {"name": "value"}

picocli strips out the double quotes on windows but leaves them on linux (the desired behaviour).
I have switched on picocli debug and see the following debug, which shows the difference when run on windows and on linux

[picocli INFO] Parsing 12 command line args ... 

Am i missing something obvious?

I am using cygwin shell on windows, bash shell on linux. 
I am using picocli 4.5.2

Thanks for any help

Carl

Carl Saint

unread,
Nov 23, 2020, 4:16:22 PM11/23/20
to picocli
The code below shows the different output when run on either linux or windows. I need to preserve the quotes for valid JSON

Code:
------------
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package picocli.demo;

import java.util.concurrent.Callable;

import picocli.CommandLine;
import picocli.CommandLine.Option;

public class App implements Callable<Integer>
{
    @Option(names="--json", description="valid json")
    String json;

    @Override
    public Integer call() throws Exception { // your business logic goes here...
        System.out.println("JSON - "+json);
        return 0;
    }

    public static void main(String[] args)
    {  
        int exitCode = new CommandLine(new App()).execute(args);

        System.out.println("Exitcode - "+exitCode);
    }
}
--------------
Linux:
# java -jar picocli-demo.jar --json='{ "name": "value" }'
JSON - { "name": "value" }
Exitcode - 0

Windows:
$ java -jar picocli-demo.jar --json='{ "name": "value" }'
JSON - { name: value }
Exitcode - 0



Remko Popma

unread,
Nov 23, 2020, 9:20:32 PM11/23/20
to picocli
I am getting slightly different results on Windows (see below), but it looks like two things are happening on the Windows Command Prompt shell:
  • the CMD shell strips out double quotes
  • single quotes do not have special meaning in the command prompt shell: 'a b' is interpreted by the shell as two arguments: ['a] and [b']
I modified your program a bit to also print the raw args as they are passed by the command prompt shell to the Java process:

public class QuotingDemo implements Runnable {
  @Option(names = "--json", description = "valid json")
  String json;

  @Override
  public void run() {
    System.out.println("JSON - " + json);

  }

  public static void main(String[] args) {
    System.out.println("Args=" + Arrays.toString(args));
    int exitCode = new CommandLine(new QuotingDemo()).execute(args);

    System.out.println("Exitcode - " + exitCode);
  }
}


On the Windows command prompt, I see this:

java -cp "c:\Users\remko\picocli-4.5.2.jar;." QuotingDemo --json='{"name": "value"}'
Args=[--json='{name:, value}']
Unmatched argument at index 1: 'value}''
Usage: <main class> [--json=<json>]
      --json=<json>   valid json
Exitcode - 2

Note that the raw args no longer contain double quotes, and the args array contains two elements: the first is --json='{name:, and the second is value}'.
Picocli then shows an error for the second argument (value}').

So, on the Windows command prompt, users can only quote using double quotes.
When the option parameter is quoted with double quotes in CMD prompt, the Java process receives a single argument (as intended):

java -cp "c:\Users\remko\picocli-4.5.2.jar;." QuotingDemo --json="{'name': 'value'}"
Args=[--json={'name': 'value'}]
JSON - {'name': 'value'}
Exitcode - 0

Note that PowerShell has different quoting rules than CMD prompt: https://stackoverflow.com/a/63627261/1446916


The linux shell is more powerful and allows quoting with both single and double quotes.
On linux I see single quotes work as intended: the raw args array contains a single element:

java -cp /mnt/c/Users/remko/picocli-4.5.2.jar:. QuotingDemo --json='{"name": "value"}'
Args=[--json={"name": "value"}]
JSON - {"name": "value"}
Exitcode - 0

Similarly when the option parameter is quoted with double quotes:

java -cp /mnt/c/Users/remko/picocli-4.5.2.jar:. QuotingDemo --json="{'name': 'value'}"
Args=[--json={'name': 'value'}]
JSON - {'name': 'value'}
Exitcode - 0

Remko Popma

unread,
Nov 23, 2020, 9:30:46 PM11/23/20
to picocli
I just saw you mentioned using cygwin on Windows.
The cygwin bash shell seems to work similar as Linux for me: both double quotes and single quotes are respected.
The following output is from Cygwin (with mintty 2.9.0):

$ java -cp "picocli-4.5.2.jar;." QuotingDemo --json='{"name": "value"}'
Args=[--json={"name": "value"}]
JSON - {"name": "value"}
Exitcode - 0

$ java -cp "picocli-4.5.2.jar;." QuotingDemo --json="{'name': 'value'}"
Args=[--json={'name': 'value'}]
JSON - {'name': 'value'}
Exitcode - 0


Carl Saint

unread,
Nov 24, 2020, 6:17:57 AM11/24/20
to picocli
Thanks for your reply. It does just seem to be a shell difference. I could not get the cygwin to work as you showed above, but it works when i escape the quotes when using cygwin terminal on windows -

$ java  -jar picocli-demo.jar --json='{ \"name\": \"value\" }' 
Args=[--json={ "name": "value" }]
JSON - { "name": "value" }
Exitcode - 0

Many thanks

Reply all
Reply to author
Forward
0 new messages