I am using JCommander(version 1.32) to parse command line arguments passed to a java application(let's call it app
). The problem I have is that one of the arguments I need to pass begins with @
and as can be seen here there is a special syntax for @
. Thus calling the app with app @arg
fails with
Could not read file arg: java.io.FileNotFoundException: arg (No such file or directory).
Reading through this information I tried placing my arguments in a file but apparently the "@ syntax" is recursive thus even when I place @arg
in a file my program fails with the same error.
Is there a way to pass an argument that begins with @
to a program that uses jcommander? Is there a way to disable the @
syntax?
As a result of the chat discussion about this between OP and myself, we came to the following conclusion:
JCommander calls itself, as part of the way it parses commands - subcommand structures that each have their own parameter definitions.
At the top level it expands the @-parameter and creates a new argument list that includes the contents of the file.
Then, as it calls itself, it parses that argument list again, and therefore expands any parameters beginning with a @
once again.
Luckily, it appears it only does so once, so it is not fully recursive. So the solution for anybody wanting to pass a parameter that begins with @
is to use two indirections. That is, create two files:
file1.txt
@file2.txt
file2.txt
@actualparameter
And then use @file1.txt
on the command line itself.
So this is a possible workaround. Personally, I'm not too happy about creating extra files like that, and I'd suggest one of three other solutions:
@
mechanism or ask the original author to do so himself.@
, and then strip that character when I need to use the parameter's value. At least this doesn't create two extra files.There is a new method, according to the comments to this pull request on Jcommander's github that allows disabling the processing of the @
sign. E.g.
JCommander jc = new JCommander(params);
jc.setExpandAmpersat(false);
The method has been added starting with version 1.54.
Disabling the feature altogether
You can disable the expansion of the @
parameters via:
jc.setExpandAmpersat(false)
(as noted in this answer)jc.setExpandAtSign(false)
(in some versions)There is also a corresponding option on the builder
Using indirection with a file
If you absolutely rely on @
in your commandline parsing, and you expect that your users need to pass filenames or other parameters that start with @
, you could ask them to use indirection using extra files.
E.g. to pass filename @foo
to --file
, write @foo
on a single line of a text file, and pass that file via --file @textfile
. The expansion is not recursive.
This doesn't work in all situations. But you could convince yourself this is acceptable.
Escaping arguments starting with @
It should be noted that JCommander only expands @
if they start the argument. Knowing this, and assuming you already have some control over argument parsing in your program, you could leave the JCommander default behavior alone, but ask users to explicitly disable it per-argument, using an escape character prefix .
e.g. You could establish a convention where if a user wishes to pass a filename "@foo" (or say, a twitter handle) on the command line, they can prefix it with a backslash or a space: --file " @foo"
or --file "\\@foo"
. This will prevent the automatic expansion by JCommander, but then your code needs to detect and strip that extra character before further argument processing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With