Quotes in command line arguments passed to Java main() - java

I run a Java program with the following command line (Edit: in NetBeans 6.8 project properties)
toto has:"tutu titi"
args is an array of 2 Strings
toto
has:tutu titi
I want (two arguments indeed, the second) args[1] to be
has:"tutu titi"
How should I do that?
Edit: I have already tried escaping the quotes with backslash from "Arguments" line in Netbeans propject properties, but I get args[1]
has:\tutu titi\

This really depends on your shell. You haven't said what operating system you're using. For example, on Windows this will work:
java Test toto "has:\"tutu titi\""
I believe the same thing will work in bash, too.
But if you're asking what you can do within Java to resolve this: nothing. The shell will have parsed the command line before the process was invoked, and you can't undo that parsing.

I had a similar problem in NetBeans and found the solution:
Edit/Add the property "application.args" in your private.properties to this:
application.args='has:""tutu titi""'
Single quotes to mark your "argument" and two double quotes to define one "double quotes".

Use
toto "has:\"tutu titi\""

If adding from NetBeans (7.1.2) Configuration/Arguments dialog field, a single-quote outer and escaped double quote inner worked for me e.g.:
my argument

This has been recognised by netbeans as a bug that won't be fixed!

Related

Passing a space separated value via shell is taking more argument then expected

I'm having difficulties to startup a java program from a shell script (bash) where nested variables are used
export MAIN_CLASS="xxxxx"
MAIN_CLASS_ARGS=("$FirstArg" "$SEC_ARG" )
CMD="java some args here ${MAIN_CLASS} ${MAIN_CLASS_ARGS[#]}"
exec $CMD
And I am passing parameter as
export FirstArg = hello
export SEC_ARG ="hi Jam"
But In my main java class I have getting 3 parameter hello, hi ,Jam. But I am expecting it to be only two. What I am missing here can anyone help me.
I have checked some of the link as
link
But not able to fix it.
When you run exec $CMD, then word splitting is performed on the contents of $CMD. It doesn't matter how the variable was built up; at this point, it's just a string which is split by the shell.
Since you appear to be using a shell with support for arrays, then one option would be to do this instead:
CMD=( java some args here "${MAIN_CLASS}" "${MAIN_CLASS_ARGS[#]}" )
exec "${CMD[#]}"
That is, build up an array of all the arguments, then use a quoted array expansion, which prevents word splitting from taking place.

java reads "*" in args[0] as the .class file

I want some code in my program to run only if the user has input the character '*' at the command-line as a command-line argument. This is the code I've used:-
//myfile.java
import java.io.*;
public class myfile {
public static void main(String[] args) {
if(args[0].equals("*")){
//do stuff
System.out.println(args[0]);//added this line to see what exactly was being passed
}
}
}
When this program is executed at the command-line by entering:-
java myfile *
the output I'm expecting to see on the screen is the asterisk character, instead the output displayed is 'myfile.class'. Where am I going wrong? Why does Java change the asterisk to the .class file?
Also, note that the program worked perfectly the first four times I executed it and then started doing this!
Thanks in advance for your help.
Where am I going wrong?
The star character needs to be quoted or escaped. Run your java program like this:
java myfile "*"
or
java myfile \*
Why does Java change the asterisk to the .class file?
It doesn't. It is your shell that is doing it. It is shell file expansion ... or "globbing" as it is also called.
Run "ls *" or "echo *" and you will see that the same thing happens.
The command terminal already replaces the asterisk and java already gets the value that you see. I'd use any other character, that has no special meaning to the command terminal or otherwise you must escape the asterisk in your command.
Actually escaping arguments on Windows and especially in cmd.exe is non-trivial. This nice article explains it in detail: Everyone quotes command line arguments the wrong way :
the takaway for your case is: surround the asterisk with quotes.
Answer to your question in the comment:
Using the escape character worked! But I still don't get why it worked without the escape character the first few times
I am not sure, but maybe you run into this behavior: It makes a difference if the pattern can be expanded or not. For example, when I pass Test* as argument, then there are 2 cases to consider:
in the current folder there is a file called Test1.txt: then your java program will get Test1.txt as argument
when there are no matching files, your program will get Test* as argument
However, I am not sure, how this would apply to your case, since you only pass *: that should only work in an empty directory.

How to replace a single line in .sh with Java?

I have a .sh script with a property=value. Let it be:
some_property="some value"
The value of the property is used along the script and script is launched in Java code. I want to dynamically change this property's value. I tried to use replaceFirst() method, but I don't know the actual value of "some_property" to replace it correctly using regexp.
How can I edit a .sh file with replacing a single line that starts with "some_property=" by some_property=my_value? By the way there're several places in a file where pattern "some_property=" can be met, so I need to change the first occurrence.
You should be fine with a regex:
line.replaceFirst("some_property=.*$", "some_property=\"" + your_value + "\"");
You can get position of the = and \n using String.indexOf(int) and then replace the string between = and \n using, for example, replace(CharSequence, CharSequence).
Btw - some_property=(.+) (and replacing $1) wouldn't be okay? :)

use attr linux command from Java program

I want to attach meta data to a file in Unix file system.
attr command lets me do that but
the command syntax requires the path of the attached variable to be in double qoutes.
attr -s outpipe0 "/mnt/FUse/FileB" FileA
how can i Use System.Runtime.exec in java to run the above command. When ever i try to run using a string array argument I have to give the above "/mnt/FUse/FileB" which causes problem in java program as it considers the double quotes as end of string in java. I basically want to send a string argument which in itself has double quotes.
Can someone suggest a work around .
Thanks
You can escape the quotes within your literal string in Java, like this:
"\"/mnt/FUse/FileB\""
That will address your question of how to include double quotes in a string, but I doubt it will solve your program. That's because I doubt the attr program actually wants (or accepts) double quotes. Instead, the shell eats them. For example, if the command you type in the shell is the one you mentioned, the double quotes will be consumed by the shell before the arguments are passed to attr. So I have doubts that you need the double quotes at all (but if you do, see above).

The issue of * in Command line argument

I wrote a program in Java that accepts input via command line arguments.
I get an input of two numbers and an operator from the command line.
To multiply two numbers, I have to give input as e.g. 5 3 *, but it's not working as written.
Why is it not accepting * from the command line?
That's because * is a shell wildcard: it has a special meaning to the shell, which expands it before passing it on to the command (in this case, java).
Since you need a literal *, you need to escape it from the shell. The exact way of escaping varies depending on your shell, but you can try:
java ProgramName 5 3 "*"
Or:
java ProgramName 5 3 \*
By the way, if you want to know what the shell does with the *, try printing the content of String[] args to your main method. You'll find that it will contain names of the files in your directory.
This can be handy if you need to pass some filenames as command line arguments.
See also
Wikipedia: glob
For example, if a directory contains two files, a.log and b.log then the command cat *.log will be expanded by the shell to cat a.log b.log
Wikipedia: Escape character
In Bourne shell (sh), the asterisk (*) and question mark (?) characters are wildcard characters expanded via globbing. Without a preceding escape character, an * will expand to the names of all files in the working directory that don't start with a period if and only if there are such files, otherwise * remains unexpanded. So to refer to a file literally called "*", the shell must be told not to interpret it in this way, by preceding it with a backslash (\).
Under MS WINDOWS not quite true: "java.exe" silently expands command line arguments with the wildcards
*
?
[abc]
, but only in the last component, so
a/*/*
does not work as you may expect.
It also ignores the entries "." and "..", but does honor other file names starting with ".".
To avoid misunderstandings: If I look at the command line of the running JAVA process with PROCEXP, I see the unexpanded args!
I found no way to work around this. In other words: As long as you have at least one file or directory in the current directory, "java Calc 3 * 7" will NOT work!
This is VERY ugly, and seems to always having been there in all JRE versions up to and including Java 8.
Does anybody have an idea how to disable Java's nasty command line expansion?
* has special meaning in shell interpreters. How to get a * literally is depending on what shell interpreter you are using. For Bash, you should put single quotes around the *, i.e. '*', instead of double quotes like "*".
Try surrounding the * with quotes like "*". The star is a reserved symbol on the command line.
Use single quotes:
java FooBar 5 3 '*'
This works with most of the popular shells (including bash and ksh).
Expanding on #Arno Unkrig's answer:
On Windows, some JVMs definitely do expand the "*" character, and it is not the shell expanding the path. You can confirm this by writing a small Java program that prints out the arguments:
public class TestArgs {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("Arg " + i + ": " + args[i]);
}
}
}
The good news is, there is a workaround! You can use #filename as an argument to JVM like this:
java #args.txt where args.txt is a text file that contains the arguments for each line. Example content:
TestArgs
*
This is equivalent to calling java with two arguments TestArgs and *. Most importantly, * is not expanded when it is included using the #filename method. I was able to find the details from this page.

Categories